public void ReplaceCurrentSketching(TemplatePack template)
        {
            GOMLib.GOM_Object_Primitive	primitive;

            if (status.Action == UserActions.Sketching)
            {
                m_sketch = null;

                primitive = new GOMLib.GOM_Object_Primitive();
                primitive.InitializeFromTemplate(template.template);

                primitive.xOffset	= template.rect.Left;
                primitive.yOffset	= template.rect.Top;

                GOMLib.GOM_Default_Values.ScaleObject(primitive, 25, 25);
            //				GOMLib.GOM_Default_Values.ScaleObject(primitive, template.rect.Width, template.rect.Height);
            /*
                double rotation = (template.rotation / System.Math.PI) * 180;

                if (rotation < 0)
                {
                    rotation += 360;
                }
                rotation = (float)System.Math.Round(rotation / 45) * 45;

                primitive.rotation	= (float)rotation;
            */
                m_rgObjects.Add(primitive);
                //save to somewhere
                //end

                m_sketch = new GOMLib.GOM_Object_Sketch();
                tagFishEye.ClearFishEyeItems();

                DrawObjectsOnCanvas();
            }
        }
        public DrawingForm(string templatePath)
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
            m_LButtonPressed	= false;
            m_CtrlPressed		= false;
            m_bRedoing			= false;

            m_selectingRect	= new System.Drawing.Rectangle(0, 0, 0, 0);
            m_selectedPen	= new Pen(System.Drawing.Color.FromArgb(150, 0, 0, 255), 1);
            m_groupSelPen	= new Pen(System.Drawing.Color.FromArgb(255, 200, 200, 200), 1);
            m_selectingPen	= new Pen(System.Drawing.Color.FromArgb(100, 0, 0, 0), 1);
            m_groupSelPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
            m_selectingPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;

            m_frmColor					= new ColorForm();
            m_frmColor.TopLevel			= false;
            m_frmColor.FormBorderStyle	= FormBorderStyle.None;
            m_frmColor.Visible			= false;
            m_frmColor.DrawingStyleChanged	+= new DrawingStyleChangedEvent(m_frmColor_DrawingStyleChanged);
            m_frmColor.FillingStyleChanged	+= new FillingStyleChangedEvent(m_frmColor_FillingStyleChanged);

            m_frmEdit					= new EditForm();
            m_frmEdit.TopLevel			= false;
            m_frmEdit.FormBorderStyle	= FormBorderStyle.None;
            m_frmEdit.Visible			= false;
            m_frmEdit.CommandSelected	+= new CommandSelectedEvent(m_frmEdit_CommandSelected);

            m_frmLink					= new LinkForm();
            m_frmLink.TopLevel			= false;
            m_frmLink.FormBorderStyle	= FormBorderStyle.None;
            m_frmLink.Visible			= false;
            m_frmLink.LinkStyleChanged	+= new LinkStyleChangedEvent(m_frmLink_LinkStyleChanged);
            m_frmLink.RemoveLink		+= new RemoveLinkEvent(m_frmLink_RemoveLink);

            m_frmInfo = new InfoForm();
            m_frmInfo.TopLevel = false;
            m_frmInfo.FormBorderStyle = FormBorderStyle.None;
            m_frmInfo.Visible = false;
            m_frmInfo.DrawingInfoChanged += new DrawingInfoChanged(m_frmInfo_DrawingInfoChanged);
            tagInfo.TagControl = m_frmInfo;
            //m_frmLink.LoadLinkStyle(Environment.CurrentDirectory + "\\Links");

            tagColor.TagControl	= m_frmColor;
            tagEdit.TagControl	= m_frmEdit;
            tagLink.TagControl	= m_frmLink;

            m_clipBoard	= new GOMLib.GOM_Objects();
            m_selObjs	= new GOMLib.GOM_Objects();
            m_rgObjects	= new GOMLib.GOM_Objects();
            m_bitmap	= new Bitmap(plDraw.Width, plDraw.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            m_preprocess = new PreprocessQueue();
            m_preprocess.m_bDebugging	= false;
            m_preprocess.UpdateRequired += new PreprocessOverEvent(m_preprocess_UpdateRequired);
            m_preprocess.StartPreprocessThread();

            m_recognition = new RecognitionQueue(templatePath);
            m_recognition.m_bDebugging		= false;
            m_recognition.RecognitionStart	+= new RecognitionEvent(m_recognition_RecognitionStart);
            m_recognition.RecognitionEnd	+= new RecognitionEvent(m_recognition_RecognitionEnd);
            m_recognition.RecognitionOver	+= new RecognitionOverEvent(m_recognition_RecognitionOver);
            m_recognition.StartRecognitionThread();

            m_rgRedoList= new ArrayList();
            m_rgLinks	= new GOMLib.GOM_Links();
            m_rgStroke	= null;
            m_sketch	= null;

            m_selectedPoint	= null;
            m_selectedLink	= null;
            m_selectedLinkKeyPoint = null;

            m_tracker = new MouseTrackerLib.CTrackerClass();

            Graphics.FromImage(m_bitmap).FillRectangle(System.Drawing.Brushes.White, 0, 0, plDraw.Width, plDraw.Height);
        }
        private void PreprocessThread()
        {
            GOMLib.GOM_Object_Sketch		sketchObj;
            System.Collections.ArrayList	sketch;

            while (!m_bTerminating)
            {
                m_QueueNotEmpty.WaitOne();

                sketch		= null;
                sketchObj	= null;

                m_Mutex.WaitOne();

                if (m_bTerminating)
                {
                    m_Mutex.ReleaseMutex();
                    return;
                }
                else if ((m_rgSketchObj.Count > 0) && (m_rgSketch.Count > 0))
                {
                    sketchObj	= (GOMLib.GOM_Object_Sketch)m_rgSketchObj[0];
                    sketch		= (System.Collections.ArrayList)m_rgSketch[0];

                    m_rgSketchObj.RemoveAt(0);
                    m_rgSketch.RemoveAt(0);

                    if ((m_rgSketchObj.Count == 0) || (m_rgSketch.Count == 0))
                    {
                        m_QueueNotEmpty.Reset();
                    }
                }

                m_Mutex.ReleaseMutex();

                try
                {
                    if ((sketch != null) && (sketchObj != null))
                    {
                        m_curSketchObj		= sketchObj;
                        HandlePreprocessResult(m_preprocess.RecognizeStroke(EncodeSketchToXML(sketch)));
                    }
                }
                catch
                {
                    System.Windows.Forms.MessageBox.Show("Exception occurs on stroke recognition.");
                    m_preprocess = null;
                    m_preprocess = new Preprocessing.CStrokeRecognitionClass();
                }
            }
        }
        public void FinishCurrentSketchObject()
        {
            m_recognition.StopRecognize();

            status.Action = UserActions.Editing;
            if ( DrawingModeChanged != null )
            {
                DrawingModeChanged(DrawingMode.Editing);
            }

            FinishCurrentSketchStroke();

            if (m_sketch != null)
            {
                if (m_sketch.rgSketchSet.Count > 0)
                {
                    m_selObjs.Clear();
                    m_selObjs.Add(m_sketch);
                    m_rgObjects.Add(m_sketch);
                    m_sketch.CalculateBoundingBox();
                }
                m_sketch = null;
            }
        }
        private void HandlePreprocessResult(string result)
        {
            if (m_curSketchObj != null)
            {
                DecodeXMLToStroke(result);
                ReloadStrokesFromXML(m_curSketchObj, m_refine.Refine_MergeVertex(m_curSketchObj.ExportRecognitionResultToXML(), 10));
            }
            m_curSketchObj = null;

            if (UpdateRequired != null)
            {
                UpdateRequired();
            }
        }
        public void PushSketchAndWait(GOMLib.GOM_Object_Sketch sketchObj, System.Collections.ArrayList sketch)
        {
            m_Mutex.WaitOne();

            m_curSketchObj		= sketchObj;
            HandlePreprocessResult(m_preprocess.RecognizeStroke(EncodeSketchToXML(sketch)));

            m_Mutex.ReleaseMutex();
        }
        public PreprocessQueue()
        {
            UpdateRequired	= null;
            m_curSketchObj	= null;
            m_bTerminating	= false;
            m_bDebugging	= false;

            m_debugSketch	= null;
            m_debugStroke	= null;
            m_rgSketchObj	= new ArrayList();
            m_rgSketch		= new ArrayList();

            m_preprocess	= new Preprocessing.CStrokeRecognitionClass();
            m_refine		= new StrokeRefineLib.CStrokeRefinementClass();

            m_WorkerThread	= new System.Threading.Thread(new System.Threading.ThreadStart(PreprocessThread));
            m_Mutex			= new System.Threading.Mutex();
            m_QueueNotEmpty	= new System.Threading.ManualResetEvent(false);
        }
        private void plDraw_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            GOMLib.GOM_Interface_Graphic_Object	selectedObj;

            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                m_LButtonPressed = true;
            }

            switch (e.Button)
            {
                case System.Windows.Forms.MouseButtons.Right:
                {
                    if ( m_selectedLink!= null && m_selectedLink.IsPointOnLink(e.X, e.Y, m_rgObjects) )
                    {
                        m_selectedLink.AddKeyPoint(e.X, e.Y, m_rgObjects);
                        DrawObjectsOnCanvas();
                    }
                    else
                    {
                        if (status.Action == UserActions.Sketching)
                        {
                            if (!m_LButtonPressed)
                            {
                                FinishCurrentSketchObject();
                            }
                        }
                        else
                        {
                            ClearRecognitionResult();
                            m_sketch = new GOMLib.GOM_Object_Sketch();
                            status.Action = UserActions.Sketching;
                            if ( DrawingModeChanged != null )
                            {
                                DrawingModeChanged(DrawingMode.Sketching);
                            }

                        }

                        DrawObjectsOnCanvas();
                    }
                    break;
                }
                case System.Windows.Forms.MouseButtons.Left:
                {
                    switch (status.Action)
                    {
                        case UserActions.Sketching:
                        {
            //							FinishCurrentSketchStroke();

                            ClearRecognitionResult();
                            DrawObjectsOnCanvas();

                            m_orgX		= -1;
                            m_orgY		= -1;
                            m_rgStroke	= new ArrayList();
                            m_tracker.StartTracker(true);

                            break;
                        }
                        case UserActions.Editing:
                        {
                            GOMLib.GOM_Link	link;

                            plDraw.Capture	= true;

                            selectedObj				= null;
                            m_orgX					= e.X;
                            m_orgY					= e.Y;
                            m_selectedLinkKeyPoint	= null;

                            //Ckeck for link key point at the mouse position
                            if ( m_selectedLink != null && m_selObjs.Count<=0 )
                            {
                                for( int i=0; i<m_selectedLink.m_keyPts.Count; i++)
                                {
                                    if ( GOMLib.GOM_Default_Values.IsMouseOnPoint(m_selectedLink.m_keyPts[i].x, m_selectedLink.m_keyPts[i].y, e.X, e.Y ) )
                                    {
                                        m_selectedLinkKeyPoint = m_selectedLink.m_keyPts[i];
                                        status.Action = UserActions.MovingKeyPoint;
                                        if ( DrawingModeChanged != null )
                                        {
                                            DrawingModeChanged(DrawingMode.Editing);
                                        }

                                        return;
                                    }
                                }
                            }

                            //Check for object at the mouse position
                            for (int i = m_rgObjects.Count - 1; i >= 0; i--)
                            {
                                if (m_rgObjects[i].IsPointInObject(e.X, e.Y))
                                {
                                    selectedObj = m_rgObjects[i];

                                    if (!m_selObjs.Contains(selectedObj))
                                    {
                                        if (!m_CtrlPressed)
                                        {
                                            m_selObjs.Clear();
                                        }
                                        m_selObjs.Add(selectedObj);
                                    }
                                    status.Action = UserActions.Moving;
                                    if ( DrawingModeChanged != null )
                                    {
                                        DrawingModeChanged(DrawingMode.Editing);
                                    }
                                    DrawObjectsOnCanvas();

                                    return;
                                }
                            }

                            m_selectedLink = null;
                            for (int i = 0; i < m_rgLinks.Count; i++)
                            {
                                link = (GOMLib.GOM_Link)m_rgLinks[i];

                                if (link.IsPointOnLink(e.X, e.Y, m_rgObjects))
                                {
                                    m_selObjs.Clear();
                                    m_selectedLink = link;
                                    DrawObjectsOnCanvas();

                                    return;
                                }
                            }
                            //Check for controllable points
                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_selectedPoint = m_selObjs[i].GetMovablePointAt(e.X, e.Y);

                                if (m_selectedPoint != null)
                                {
                                    status.Action	= UserActions.Controlling;
                                    selectedObj		= m_selObjs[i];

                                    m_selObjs.Clear();
                                    m_selObjs.Add(selectedObj);
                                    DrawObjectsOnCanvas();

                                    return;
                                }
                            }
                            //Check for connectable points
                            for (int i = 0; i < m_rgObjects.Count; i++)
                            {
                                m_selectedPoint = m_rgObjects[i].GetConnectablePointAt(e.X, e.Y);

                                if (m_selectedPoint != null)
                                {
                                    status.Action	= UserActions.Linking;
                                    selectedObj		= m_rgObjects[i];

                                    m_selObjs.Clear();
                                    m_selObjs.Add(selectedObj);
                                    DrawObjectsOnCanvas();

                                    return;
                                }
                            }
                            //A object is selected. Update the selection list
                            if (selectedObj != null)
                            {
                                if (!m_selObjs.Contains(selectedObj))
                                {
                                    if (!m_CtrlPressed)
                                    {
                                        m_selObjs.Clear();
                                    }
                                    m_selObjs.Add(selectedObj);
                                }
                                status.Action = UserActions.Moving;
                                if ( DrawingModeChanged != null )
                                {
                                    DrawingModeChanged(DrawingMode.Editing);
                                }

                            }
                            else
                            {
                                if (!m_CtrlPressed)
                                {
                                    m_selObjs.Clear();
                                }

                                m_orgX = e.X;
                                m_orgY = e.Y;

                                status.Action = UserActions.Selecting;
                                if ( DrawingModeChanged != null )
                                {
                                    DrawingModeChanged(DrawingMode.Editing);
                                }

                            }
                            DrawObjectsOnCanvas();
                            break;
                        }
                        case UserActions.InsertObject:
                        {
                            break;
                        }
                    }
                    break;
                }
            }
        }
        private void m_frmEdit_CommandSelected(EditCommands command)
        {
            if (status.Action == UserActions.Editing)
            {
                switch (command)
                {
                    case EditCommands.Group:
                    {
                        if (m_selObjs.Count > 1)
                        {
                            GOMLib.GOM_Interface_Graphic_Object	obj;

                            obj = GOMLib.GOM_Object_Group.CreateGroupObject(m_selObjs);

                            if (obj != null)
                            {
                                for (int i = 0; i < m_selObjs.Count; i++)
                                {
                                    m_rgObjects.Remove(m_selObjs[i]);
                                }

                                m_rgObjects.Add(obj);

                                m_selObjs.Clear();
                                m_selObjs.Add(obj);

                                DrawObjectsOnCanvas();
                            }
                        }
                        break;
                    }
                    case EditCommands.Ungroup:
                    {
                        if (m_selObjs.Count == 1)
                        {
                            if (m_selObjs[0] is GOMLib.GOM_Object_Group)
                            {
                                GOMLib.GOM_Objects	rgObjs;

                                rgObjs = new GOMLib.GOM_Objects();

                                ((GOMLib.GOM_Object_Group)m_selObjs[0]).DecomposeGroupObject(rgObjs);

                                m_rgObjects.Remove(m_selObjs[0]);
                                m_selObjs.Clear();

                                for (int i = 0; i < rgObjs.Count; i++)
                                {
                                    m_rgObjects.Add(rgObjs[i]);
                                    m_selObjs.Add(rgObjs[i]);
                                }

                                DrawObjectsOnCanvas();
                            }
                        }
                        break;
                    }
                    case EditCommands.BringToFront:
                    {
                        if (m_selObjs.Count > 0)
                        {
                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_rgObjects.Remove(m_selObjs[i]);
                            }

                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_rgObjects.Add(m_selObjs[i]);
                            }

                            DrawObjectsOnCanvas();
                        }
                        break;
                    }
                    case EditCommands.SendToBack:
                    {
                        if (m_selObjs.Count > 0)
                        {
                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_rgObjects.Remove(m_selObjs[i]);
                            }

                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_rgObjects.Insert(m_selObjs[i], 0);
                            }

                            DrawObjectsOnCanvas();
                        }
                        break;
                    }
                    case EditCommands.Delete:
                    {
                        if (m_selObjs.Count > 0)
                        {
                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_rgObjects.Remove(m_selObjs[i]);

                                int j = 0;

                                while (j < m_rgLinks.Count)
                                {
                                    if (((GOMLib.GOM_Link)m_rgLinks[j]).LinkWith(m_selObjs[i]))
                                    {
                                        if (m_rgLinks[j].Equals(m_selectedLink))
                                        {
                                            m_selectedLink = null;
                                        }

                                        m_rgLinks.RemoveAt(j);
                                    }
                                    else
                                    {
                                        j++;
                                    }
                                }
                            }

                            m_selObjs.Clear();
                            DrawObjectsOnCanvas();
                        }
                        break;
                    }
                    case EditCommands.Cut:
                    {
                        if (m_selObjs.Count > 0)
                        {
                            m_clipBoard.Clear();

                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_rgObjects.Remove(m_selObjs[i]);
                                m_clipBoard.Add(m_selObjs[i]);
                            }

                            m_selObjs.Clear();
                            DrawObjectsOnCanvas();
                        }
                        break;
                    }
                    case EditCommands.Copy:
                    {
                        if (m_selObjs.Count > 0)
                        {
                            m_clipBoard.Clear();

                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_clipBoard.Add(m_selObjs[i]);
                            }
                        }
                        break;
                    }
                    case EditCommands.Paste:
                    {
                        if (m_clipBoard.Count > 0)
                        {
                            float	minX, minY;

                            m_selObjs.Clear();

                            for (int i = 0; i < m_clipBoard.Count; i++)
                            {
                                m_selObjs.Add(m_clipBoard[i].Clone());
                            }

                            minX = m_selObjs[0].xOffset;
                            minY = m_selObjs[0].yOffset;

                            for (int i = 1; i < m_selObjs.Count; i++)
                            {
                                minX = Math.Min(minX, m_selObjs[i].xOffset);
                                minY = Math.Min(minY, m_selObjs[i].yOffset);
                            }

                            minX = tagEdit.Left - minX;
                            minY = tagEdit.Top - minY;

                            for (int i = 0; i < m_selObjs.Count; i++)
                            {
                                m_selObjs[i].xOffset += minX;
                                m_selObjs[i].yOffset += minY;

                                m_rgObjects.Add(m_selObjs[i]);
                            }

                            DrawObjectsOnCanvas();
                        }
                        break;
                    }
                    case EditCommands.Sketch:
                    {
                        if (m_selObjs.Count == 1)
                        {
                            if (m_selObjs[0] is GOMLib.GOM_Object_Sketch)
                            {
                                m_sketch = (GOMLib.GOM_Object_Sketch)m_selObjs[0];

                                m_rgObjects.Remove(m_sketch);
                                m_selObjs.Clear();

                                status.Action = UserActions.Sketching;
                                if ( DrawingModeChanged != null )
                                {
                                    DrawingModeChanged(DrawingMode.Sketching);
                                }

                                DrawObjectsOnCanvas();
                            }
                        }
                        break;
                    }
                }
            }

            if (status.Action == UserActions.Sketching)
            {
                switch (command)
                {
                    case EditCommands.Undo:
                    {
                        if (m_sketch != null)
                        {
                            while (m_sketch.rgStrokeToSketch.Count > 0)
                            {
                                if ((int)(m_sketch.rgStrokeToSketch[m_sketch.rgStrokeToSketch.Count - 1]) == m_sketch.rgSketchSet.Count)
                                {
                                    m_sketch.rgStrokeToSketch.RemoveAt(m_sketch.rgStrokeToSketch.Count - 1);
                                    m_sketch.rgDrawings.RemoveAt(m_sketch.rgDrawings.Count - 1);
                                }
                                else
                                {
                                    break;
                                }
                            }

                            if (m_sketch.rgSketchSet.Count > 0)
                            {
                                m_rgRedoList.Add(m_sketch.rgSketchSet[m_sketch.rgSketchSet.Count - 1]);
                                m_sketch.rgSketchSet.RemoveAt(m_sketch.rgSketchSet.Count - 1);
                            }

                            ClearRecognitionResult();

                            if (m_sketch.rgSketchSet.Count > 0)
                            {
            //								m_recognition.PushStrokeAndWait(m_sketch.ExportRecognitionResultToXML());
                                m_recognition.PushStroke(m_sketch.ExportRecognitionResultToXML());
                            }

                            DrawObjectsOnCanvas();
                        }
                        break;
                    }
                    case EditCommands.Redo:
                    {
                        if (m_rgRedoList.Count > 0)
                        {
                            if (m_sketch != null)
                            {
                                ClearRecognitionResult();

                                m_bRedoing = true;
                                m_sketch.rgSketchSet.Add(m_rgRedoList[m_rgRedoList.Count - 1]);
                                m_preprocess.PushSketchAndWait(m_sketch, (ArrayList)m_rgRedoList[m_rgRedoList.Count - 1]);
                                m_rgRedoList.RemoveAt(m_rgRedoList.Count - 1);

                                DrawObjectsOnCanvas();
                            }
                        }
                        break;
                    }
                }
            }

            tagEdit.HideTagWindow();
        }