using System; using System.ComponentModel; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Drawing; using System.Windows.Forms; using VEPROMS.CSLA.Library; using Volian.Controls.Library; using System.Reflection; using LBWordLibrary; namespace Volian.Controls.Library { public partial class DSOTabPanel : DevComponents.DotNetBar.PanelDockContainer { #region Private Fields private DisplayTabControl _MyDisplayTabControl; private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private AxDSOFramer.AxFramerControl _MyDSOFramer; private TransparentPanel _MyTransparentPanel; private static int _Count = 0; private DocumentInfo _MyDocumentInfo; private int _MyCount; private DisplayTabItem _MyDisplayTabItem; private DSOFile _DSOFile; public static int MSWordLimit = 10; #endregion #region Public Properties private String _SearchString; public String SearchString { get { return _SearchString; } set { _SearchString = value; FindSearchString(); } } /// /// Count of DSO Pages open. Limited to 18 in DisplayTabControl /// public static int Count { get { return _Count; } set { _Count = value; } } /// /// Pointer to the related DisplayTabItem /// public DisplayTabItem MyDisplayTabItem { get { return _MyDisplayTabItem; } set { _MyDisplayTabItem = value; _MyDisplayTabItem.Visible = false; _MyDisplayTabItem.Visible = true; } } /// /// DocumentInfo record for the Word document /// public DocumentInfo MyDocumentInfo { get { return _MyDocumentInfo; } } /// /// Temporary Word file used for editing. /// internal DSOFile MyDSOFile { get { if (_DSOFile == null) _DSOFile = new DSOFile(_MyDocumentInfo); return _DSOFile; } } /// /// Dirty status. Only saved if dirty. /// public bool IsDirty { get { if (_MyDSOFramer == null) return false; LBDocumentClass doc = new LBDocumentClass(_MyDSOFramer.ActiveDocument); return !doc.Saved; } } public E_ViewMode PanelViewEditMode = E_ViewMode.Edit; #endregion //private frmPG _frm = null; #region Constructors private Timer _RefreshTimer; private ItemInfo _ItemInfo; public DSOTabPanel(DocumentInfo documentInfo, DisplayTabControl myDisplayTabControl, ItemInfo itemInfo) { _MyDisplayTabControl = myDisplayTabControl; _ItemInfo = itemInfo; InitializeComponent(); SetupDSOTabPanel(); _MyDocumentInfo = documentInfo; SetupDSO(); _RefreshTimer = new Timer(); // Enabled is false and interval is 1/10th of second. ClientSizeChanged += new EventHandler(DSOTabPanel_ClientSizeChanged); _RefreshTimer.Tick += new EventHandler(_RefreshTimer_Tick); //_frm = new frmPG(_MyDSOFramer); //_frm.Show(); } void _RefreshTimer_Tick(object sender, EventArgs e) { _RefreshTimer.Enabled = false; if(_MyDSOFramer != null) _MyDSOFramer.Focus(); } void DSOTabPanel_ClientSizeChanged(object sender, EventArgs e) { _RefreshTimer.Enabled = false; // This assures that interval is used from last event. _RefreshTimer.Enabled = true; } #endregion #region Private Methods private void SetupDSOTabPanel() { Dock = System.Windows.Forms.DockStyle.Fill; // Automatically Fill the panel } private void SetupDSO() { _Count++; // Increment the count of open Word documents (Limit = MSWordLimit) _MyCount = _Count; this._MyTransparentPanel = new TransparentPanel(); this._MyDSOFramer = new AxDSOFramer.AxFramerControl(); ((System.ComponentModel.ISupportInitialize)(this._MyDSOFramer)).BeginInit(); this.Controls.Add(this._MyDSOFramer); this.Controls.Add(this._MyTransparentPanel); // A transparent panel is added over top of the DSO Framer window so that // the related tab can be activated when the user clicks on a Word Document. Since the Word document is actually running // in a different thread, it does not behave properly with focus events. this.components.Add(this._MyDSOFramer); this.components.Add(this._MyTransparentPanel); this._MyTransparentPanel.Dock = System.Windows.Forms.DockStyle.Fill; this._MyTransparentPanel.Font = new System.Drawing.Font("Tahoma", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this._MyTransparentPanel.ForeColor = System.Drawing.Color.Brown; // This is the color used to show InActive on the right side on the Word // document menu line. //this._MyTransPanel.Location = new System.Drawing.Point(0, 0); //this._MyTransPanel.Name = "transPanel1"; //this._MyTransPanel.Size = new System.Drawing.Size(370, 423); //this._MyTransPanel.TabIndex = 1; this._MyTransparentPanel.Click += new EventHandler(_MyTransparentPanel_Click); this._MyDSOFramer.Dock = System.Windows.Forms.DockStyle.Fill; //System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WordDSOTab)); //this._DSOFramer.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("_FC.OcxState"))); ((System.ComponentModel.ISupportInitialize)(this._MyDSOFramer)).EndInit(); try { try { this._MyDSOFramer.Open(MyDSOFile.MyFile.FullName); } catch (Exception ex) { System.IO.FileStream fs = MyDSOFile.MyFile.Create(); using (DocumentAuditInfoList dail = DocumentAuditInfoList.Get(MyDocumentInfo.DocID)) { if (dail.Count > 0) { //DocumentAuditInfo dai = dail[0]; //foreach (DocumentAuditInfo tmpa in dail) //{ // if (tmpa.DTS > dai.DTS) dai = tmpa; //} if(MessageBox.Show("Do you want to revert to a previous version?", "Error in MS Word section", MessageBoxButtons.YesNo, MessageBoxIcon.Question)==DialogResult.Yes) { //fs.Write(dai.DocContent, 0, dai.DocContent.Length); using (Document myDoc = Document.Get(MyDocumentInfo.DocID)) { myDoc.RestoreWordDoc(_ItemInfo); _DSOFile = null; _MyDocumentInfo = DocumentInfo.Get(MyDocumentInfo.DocID); } } } else MessageBox.Show("Reverting to Blank Document", "Error in MS Word section", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } fs.Close(); this._MyDSOFramer.Open(MyDSOFile.MyFile.FullName); } LBDocumentClass doc = new LBDocumentClass(_MyDSOFramer.ActiveDocument); Console.WriteLine("Version {0}", doc.Application.Version); float ver; if (!float.TryParse(doc.Application.Version, out ver)) ver = 12.0F; this._MyDSOFramer.Menubar = ver < 12.0F; this._MyDSOFramer.set_EnableFileCommand(DSOFramer.dsoFileCommandType.dsoFileClose, false); this._MyDSOFramer.set_EnableFileCommand(DSOFramer.dsoFileCommandType.dsoFileNew, false); this._MyDSOFramer.set_EnableFileCommand(DSOFramer.dsoFileCommandType.dsoFilePageSetup, false); this._MyDSOFramer.set_EnableFileCommand(DSOFramer.dsoFileCommandType.dsoFilePrint, false); this._MyDSOFramer.set_EnableFileCommand(DSOFramer.dsoFileCommandType.dsoFilePrintPreview, false); this._MyDSOFramer.set_EnableFileCommand(DSOFramer.dsoFileCommandType.dsoFileProperties, false); this._MyDSOFramer.set_EnableFileCommand(DSOFramer.dsoFileCommandType.dsoFileSave, false); this._MyDSOFramer.set_EnableFileCommand(DSOFramer.dsoFileCommandType.dsoFileSaveAs, false); this._MyDSOFramer.Titlebar = false; //if (_MyCount < 20) // this._MyDSOFramer.FrameHookPolicy = DSOFramer.dsoFrameHookPolicy.dsoResetNow; this._MyDSOFramer.BeforeDocumentClosed += new AxDSOFramer._DFramerCtlEvents_BeforeDocumentClosedEventHandler(_MyDSOFramer_BeforeDocumentClosed); this._MyDSOFramer.OnSaveCompleted += new AxDSOFramer._DFramerCtlEvents_OnSaveCompletedEventHandler(_MyDSOFramer_OnSaveCompleted); //this._MyDSOFramer.LostFocus += new EventHandler(_MyDSOFramer_LostFocus); //this._MyDSOFramer.GotFocus += new EventHandler(_MyDSOFramer_GotFocus); //this._MyDSOFramer.Enter += new EventHandler(_MyDSOFramer_Enter); //this._MyDSOFramer.Leave += new EventHandler(_MyDSOFramer_Leave); //this._MyDSOFramer.OnActivationChange += new AxDSOFramer._DFramerCtlEvents_OnActivationChangeEventHandler(_MyDSOFramer_OnActivationChange); this.Enter += new EventHandler(DSOTabPanel_Enter); //this.Leave += new EventHandler(DSOTabPanel_Leave); //this.GotFocus += new EventHandler(DSOTabPanel_GotFocus); //this.LostFocus += new EventHandler(DSOTabPanel_LostFocus); Application.DoEvents(); // The following line corrects Symbol characters in MSWord Sections // CheckForSymbolCharacters(doc); InitializeWordDocument(doc); FindSearchString(); } catch (Exception ex) { string message = ShowException(ex); Console.WriteLine("\r\n-------------\r\n{0}{1}{2}\r\n-------------\r\n", MyDSOFile.MyFile.FullName, ex.GetType().Name, message); // TODO: Should output a message // TODO: Should try to do a direct open using Word. } } public void FixSymbolCharacters() { CheckForSymbolCharacters(new LBDocumentClass(_MyDSOFramer.ActiveDocument)); } private void CheckForSymbolCharacters(LBDocumentClass doc) { string fontHasSymbolCharacters = doc.FontHasSymbolCharacters; if (fontHasSymbolCharacters != null) { // do a string for the log message, depending if this is a libdoc. string msg = null; if (MyDocumentInfo.LibTitle == null || MyDocumentInfo.LibTitle == "") { if (MyDocumentInfo.DocumentEntryCount>0) msg = string.Format("Procedure = {0}, Section {1}", MyDocumentInfo.DocumentEntries[0].MyContent.ContentItems[0].MyProcedure, MyDocumentInfo.DocumentEntries[0].MyContent.ContentItems[0].DisplayText); else msg = string.Format("Procedure and Section can't be determined"); } else msg = string.Format("Library Document: {0}", MyDocumentInfo.LibTitle); if (doc.AttemptToFixASymbolCharacter()) // font is installed correctly, 'fix' this file. { //MessageBox.Show(string.Format("This document uses the font {0}, which previously had an error.\r\nThe program will attempt to fix the problem for this Word section.", fontHasSymbolCharacters), // "Font Being Corrected", MessageBoxButtons.OK); doc.FixSymbolCharacters(); _MyLog.Info(string.Format("Font problem being fixed in Font: {0}, {1}.",fontHasSymbolCharacters, msg)); } else { MessageBox.Show(string.Format("This document uses the font {0}, which has an error.\r\n\r\nReinstall this font.", fontHasSymbolCharacters), "Reinstall Font", MessageBoxButtons.OK); _MyLog.Info(string.Format("Font problem found in Font: {0}, {1}.",fontHasSymbolCharacters, msg)); } } } private void InitializeWordDocument(LBDocumentClass doc) { if (MyDocumentInfo.Config == null || MyDocumentInfo.Config == "") { DocStyle ds = MyDocumentInfo.DocumentEntries[0].MyContent.ContentItems[0].MyDocStyle; // this will cause an error and goto the Catch if the family or size is null, // Westinghouse needs it to to this - at least for now //if (ds.Font.Family != null) doc.Application.Selection.Font.Name = ds.Font.Family; //if (ds.Font.Size != null) doc.Application.Selection.Font.Size = (float)ds.Font.Size; doc.Application.Selection.Font.Name = ds.Font.Family; doc.Application.Selection.Font.Size = (float)ds.Font.Size; doc.Application.Selection.ParagraphFormat.SpaceBefore = 0; doc.Application.Selection.ParagraphFormat.SpaceAfter = 0; doc.Application.Selection.ParagraphFormat.LineSpacingRule = LBWdLineSpacing.wdLineSpaceExactly; doc.Application.Selection.ParagraphFormat.LineSpacing = 72 / 6; // for 6 LPI MSWordToPDF.AdjustMargins(ds, doc, false); } } public void FindSearchString() { if (SearchString == null) return; // Get the Document LBDocumentClass wordDoc = new LBDocumentClass(_MyDSOFramer.ActiveDocument); //LBSelection sel = wordDoc.Application.Selection; LBFind find = wordDoc.Application.Selection.Find; find.ClearFormatting(); bool wildCards = SearchString.Contains("?") || SearchString.Contains("*"); bool found = find.Execute(SearchString, false, false, wildCards, false, false, true, LBWdFindWrap.wdFindContinue, null, null, null, false, false, false, false); //Console.WriteLine("find = {0}", found); } /// /// Text will either replace current selection or be inserted at the current cursor position if no selection /// /// public void InsertText(string txt) { if (txt == null || txt.Length == 0) return; //nothing to insert // Get the Document LBDocumentClass wordDoc = new LBDocumentClass(_MyDSOFramer.ActiveDocument); //This will get the selected range or just the current cursor position LBSelection sel = wordDoc.Application.Selection; // This will replace the selection or insert at current position sel.Text = txt; } private string ShowException(Exception ex) { string sep = "\r\n "; StringBuilder sb = new StringBuilder(); do { sb.Append(sep + ex.Message); sep += " "; ex = ex.InnerException; } while (ex != null); return sb.ToString(); } //void _MyDSOFramer_Leave(object sender, EventArgs e) //{ // vlnStackTrace.ShowStack("DSO Leave {0}", this.MyDocumentInfo.DocID); //} //void _MyDSOFramer_Enter(object sender, EventArgs e) //{ // vlnStackTrace.ShowStack("DSO Enter {0}", this.MyDocumentInfo.DocID); //} //void _MyDSOFramer_GotFocus(object sender, EventArgs e) //{ // vlnStackTrace.ShowStack("DSO Got Focus {0}",this.MyDocumentInfo.DocID); //} //void _MyDSOFramer_LostFocus(object sender, EventArgs e) //{ // vlnStackTrace.ShowStack("DSO Lost Focus {0}", this.MyDocumentInfo.DocID); //} public void EnterPanel() { DSOTabPanel_Enter(this, new EventArgs()); } //void DSOTabPanel_LostFocus(object sender, EventArgs e) //{ // vlnStackTrace.ShowStack("DSOTabPanel_LostFocus {0} DocID {1} Index {2} {3}", _In_DSOTabPanel_Enter, this._MyDocumentInfo.DocID, _MyDisplayTabControl.MyBar.SelectedDockTab, sender.GetType().FullName); //} //void DSOTabPanel_GotFocus(object sender, EventArgs e) //{ // vlnStackTrace.ShowStack("DSOTabPanel_GotFocus {0} DocID {1} Index {2} {3}", _In_DSOTabPanel_Enter, this._MyDocumentInfo.DocID, _MyDisplayTabControl.MyBar.SelectedDockTab, sender.GetType().FullName); //} #endregion #region Event Handlers /// /// Display MyTransparentPanel over the DSOPanel so that the Word "Inactive" appears in the upper right hand corner. /// public void InActive() { _MyTransparentPanel.BringToFront(); } /// /// Force this item to be selected when the transparent window is clicked. /// This will in-turn send the Transparent Panel to back and make the DSO Panel /// editable. /// /// /// void _MyTransparentPanel_Click(object sender, EventArgs e) { this.Select(); } /// /// If the user presses the save button, tell the file to save it's contents to the database /// /// /// void _MyDSOFramer_OnSaveCompleted(object sender, AxDSOFramer._DFramerCtlEvents_OnSaveCompletedEvent e) { // Unfortunately, the only way to handle view mode for DSO Framer is to not save. if (PanelViewEditMode == E_ViewMode.View) { MessageBox.Show("Currently in VIEW mode,\r\n cannot Save " + _MyDisplayTabItem.Tooltip); return; } LBDocumentClass doc = new LBDocumentClass(_MyDSOFramer.ActiveDocument); while (doc.Saved = false) Application.DoEvents(); string tmp = GetReflectiveProperty(_MyDSOFramer.ActiveDocument, "FullName"); if (System.IO.File.Exists(tmp)) MyDSOFile.FullName = tmp; else _MyLog.FatalFormat("File does not exist {0}\r\nFile was {1}", tmp, MyDSOFile.FullName); // if this was a library document, ask user if it should be saved for all usages. bool cvtLibDoc = false; EntryInfo myei = MyDisplayTabItem.MyItemInfo.MyContent.MyEntry; if (myei != null && myei.MyDocument != null && myei.MyDocument.LibTitle != null && myei.MyDocument.LibTitle != "") { DialogResult ans = MessageBox.Show("Save as Library Document for all usages?", "Document Save", MessageBoxButtons.YesNo); if (ans == DialogResult.No) cvtLibDoc = true; } MyDSOFile.SaveFile(doc.Length, doc.Ascii, MyDisplayTabItem.MyItemInfo, cvtLibDoc, StatusChanged); if (cvtLibDoc) { MyDisplayTabItem.Text = MyDisplayTabItem.MyItemInfo.TabTitle; MyDisplayTabItem.Tooltip = MyDisplayTabItem.MyItemInfo.TabToolTip; MyDisplayTabItem.SetPrivateTooltip(MyDisplayTabItem.MyItemInfo.TabToolTip); } } public void StatusChanged(VolianStatusType type, int count, string text) { if (Parent != null && Parent.Parent != null && Parent.Parent.Parent is DisplayTabControl) { DisplayTabControl tc = Parent.Parent.Parent as DisplayTabControl; tc.ONStatusChanged(this, new DisplayTabControlStatusEventArgs(type, count, text)); } } /// /// Before a document closes check to see if it's contents should be saved. /// /// /// void _MyDSOFramer_BeforeDocumentClosed(object sender, AxDSOFramer._DFramerCtlEvents_BeforeDocumentClosedEvent e) { try { if (!IsBeingDeleted) SaveDirty(); this.Enter -= new EventHandler(DSOTabPanel_Enter); // this.Leave -= new EventHandler(DSOTabPanel_Leave); // SaveDirty(); // SaveDirty happens in CloseDSO(bool) } catch (Exception ex) { _MyLog.Warn("Before Closing Document ", ex); } } public static bool IgnoreEnter = false; private bool _In_DSOTabPanel_Enter=false; /// /// When a Word document is selected make sure it's tab is activated and /// the SelectedItem for the DisplayTabControl is updated. /// /// /// private void DSOTabPanel_Enter(object sender, EventArgs e) { if (IgnoreEnter) return; _MyTransparentPanel.SendToBack(); // Set whether this worddoc is in view/edit mode by checking whether the // procedure is in view/edit mode (based on the steppanel. This occurs on // the enter event so that the mode is determined any time this panel becomes // active. // find steptabpanel and its view/edit. If it doesn't have a steptabpanel // use default - edit. Later when we have ownership, need to use that. PanelViewEditMode = E_ViewMode.Edit; // default to edit if (MyDisplayTabItem.MyItemInfo != null) // lib doc with no associated active procedure defaults to edit { StepTabPanel stpanel = _MyDisplayTabControl.GetProcedureTabPanel(MyDisplayTabItem.MyItemInfo); PanelViewEditMode = (stpanel == null) ? E_ViewMode.Edit : stpanel.MyStepPanel.VwMode; } try { _MyDSOFramer.EventsEnabled = true; _MyDSOFramer.FrameHookPolicy = DSOFramer.dsoFrameHookPolicy.dsoResetNow; } catch (Exception ex) { if (_MyLog.IsErrorEnabled) _MyLog.ErrorFormat("DSOTabPage_Enter", ex); } if (_In_DSOTabPanel_Enter) return; //vlnStackTrace.ShowStack("DSOTabPanel_Enter {0} DocID {1} Index {2} {3}",_In_DSOTabPanel_Enter, this._MyDocumentInfo.DocID, _MyDisplayTabControl.MyBar.SelectedDockTab, sender.GetType().FullName); _In_DSOTabPanel_Enter = true; if (MyDisplayTabItem.MyItemInfo != null) _MyDisplayTabControl.OnItemSelectedChanged(this,new ItemSelectedChangedEventArgs(MyDisplayTabItem.MyItemInfo)); _MyDSOFramer.Focus(); _In_DSOTabPanel_Enter = false; _MyDisplayTabControl.SelectedDisplayTabItem = MyDisplayTabItem; } #endregion #region Public Methods /// /// Save the contents of the Word Document to a file /// and save the file to the database /// /// public bool SaveDSO() { bool result = true; try { _MyDSOFramer.Save(); _MyDSOFramer_OnSaveCompleted(this, null); // These are handled in the method above //LBDocumentClass doc = new LBDocumentClass(_MyDSOFramer.ActiveDocument); //MyDSOFile.FullName = GetReflectiveProperty(_MyDSOFramer.ActiveDocument, "FullName"); //MyDSOFile.SaveFile(doc.Length, doc.Ascii); } catch (Exception ex) { if (_MyLog.IsErrorEnabled) _MyLog.Error("SaveDSO", ex); result = false; } return result; } /// /// Check to see if a Word document should be saved. If it is dirty ask the user if the /// changes should be changed. Save the changes if the user says "yes". /// /// public bool SaveDirty() { if (IsDirty) { // Unfortunately, the only way to handle view mode for DSO Framer is to not save. if (PanelViewEditMode == E_ViewMode.View) { MessageBox.Show("Currently in VIEW mode,\r\n cannot Save " + _MyDisplayTabItem.Tooltip); return false; } //if (MessageBox.Show("Save changes to " + _MyDisplayTabItem.MyItemInfo.TabTitle + "\r\n" + _MyDisplayTabItem.MyItemInfo.TabToolTip, "Document has Changed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) if (MessageBox.Show("Save changes to " + _MyDisplayTabItem.Text + "\r\n" + _MyDisplayTabItem.Tooltip, "Document has Changed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) return SaveDSO(); return false; } return true; } private bool _IsBeingDeleted = false; public bool IsBeingDeleted { get { return _IsBeingDeleted; } set { _IsBeingDeleted = value; } } /// /// Cleans-up the DSO Framer window /// /// public bool CloseDSO() { return CloseDSO(false); } /// /// Cleans-up the DSO Framer window /// /// /// public bool CloseDSO(bool force) { _MyLog.Debug("CloseDSO"); bool result = true; try { if (_MyDSOFramer != null) { _MyDSOFramer.Close(); Controls.Remove(_MyDSOFramer); components.Remove(_MyDSOFramer); _MyDSOFramer.Dispose(); _MyDSOFramer = null; _Count--; } } catch (Exception ex) { if (_MyLog.IsErrorEnabled) _MyLog.Error("SaveDSO - " + this.Name, ex); result = false; } return result; } /// /// Activates the current DSO Framer window (Word) /// public void Activate() { try { this._MyDSOFramer.Activate(); if (_MyCount <= MSWordLimit) this._MyDSOFramer.FrameHookPolicy = DSOFramer.dsoFrameHookPolicy.dsoResetNow; } catch (Exception ex) { if (_MyLog.IsErrorEnabled) _MyLog.Error("Activate", ex); } } #endregion #region DocumentProperties private string GetReflectiveProperty(object objectToInspect, string propertyName) { string returnString = ""; //To use reflection on an object, you // first need to get an instance // of that object's type. Type objectType = objectToInspect.GetType(); //After you have the object's type, you can get // information on that type. In this case, we're // asking the type to tell us all the // properties that it contains. PropertyInfo[] properties = objectType.GetProperties(); //You can then use the PropertyInfo array // to loop through each property of the type. foreach (PropertyInfo property in properties) { //The interest part of this code // is the GetValue method. This method // returns the value of the property. if(property.Name == propertyName) return property.GetValue(objectToInspect, null).ToString(); } return null; } #endregion public override string ToString() { return string.Format("DSOTabPanel Document {0}", MyDocumentInfo.DocID); } } }