//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // NewTabPage.cs From SmesaFileMenu.cs // 21-Dec-2017 Rev2 begins! //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // v1.2.4.26ninja to become Rev2.2.5.27 // v1.2.5.26saphire 23-Dec-2017 // v2.2.6.27alaru 08-Jan-2018 // v2.3.7.28alfy 22-Jan-2018 Major Mods // v2.3.8.29algor 24-Jan-18 Multiple // fixes & upgrades evolved in testing // and is the best I've seen so far! // v2.5.9.30 01-Feb-2018 Perfected! // v2.5.9.31 08-Feb-2018 Editing Final. // v2.6.0.32 15-Feb-2018 SmesaMmfIpc.cs // will be more advanced code growth.^^ // v2.6.1.32 20-Feb-2018 0151 Threading. // v3.0.0.36 28-Feb-2018 0420 WPF MyApp! // v3.0.1.37 01-Mar-2018 Reverted Hybrid // v3.1.1.39 08-Mar-2018 Awesome Mods! // v3.1.3.42 20-Mar-2018 PrefClick Code. // v4.5.9.62 07-Aug-2018 Default Files. // v4.5.9.63 Omega Plan // v4.5.9.63 15-Aug-2018 Cmplt TestsWell. // v4.6.9.67 09-Sep-2018 Barely touched. // v4.8.1.77 01-Oct Debugging from FN Mods // v4.8.2.82 27-Oct Farmed out a few // static methods to MCT2 and so forth. // v5.0.5.99 15-Jan-2019 MCPL Design. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ using System; using System.IO; using System.Linq; using System.Threading; using System.Windows.Forms; using System.Collections.Generic; using System.Collections.ObjectModel; // Custom NameSpaces using MyCustomControls; // Class Aliases using MCD = MyCustomLibrary.Dialogs; using MCT = MyCustomLibrary.MyToolbox; // Property Aliases using SMS = MyEditor.Properties.Settings; using SMR = MyEditor.Properties.Resources; namespace MyEditor { public partial class Smesa // <-== NOTE { #region Rev3 Parms Passed-in Handling. // Keep This For Reference: ///// For Parms Passed in While Running! ///// Kills the earlier instance, creating new ///// that now has all the files present. ///// Awesome v2.5.9.31 08-Feb-2018 perfected. ///// //[PermissionSet(SecurityAction.Demand, // Name = "FullTrust")] //private static bool // CheckIfA2NdInstance( // string[] args, string mmfn) //{ // var processes = // Process.GetProcessesByName( // Process.GetCurrentProcess() // .ProcessName).ToList(); // if (processes.Count <= 1) // return false; // Nope. // // Yep, this IS a 2nd Instance. // processes.Sort((x, y) => // DateTime.Compare( // x.StartTime, y.StartTime)); // // Current Process Leaves a // MmfClientSideWrite( // GetCommandLine(args), mmfn); // // note and commits suicide. // processes[1].CloseMainWindow(); // return true; //} /// Allows Parms to be passed in /// loading those files as well as previously /// opened files. /// private void ParmsPassedInAtStart() { // Adds Passed in Files to Open-Files List. foreach (var file in Args .Where(file => !string.IsNullOrEmpty(file) && File.Exists(file) && !SMS.Default.FileNames .Contains(file))) SMS.Default.FileNames.Add(file); var ct = Args.Length - 1; var hit = false; for (var i = ct; i > -1; --i) { // v72mods vv if (!SMS.Default.FileNames .Contains(Args[i])) continue; SMS.Default.Index = SMS.Default .FileNames.IndexOf(Args[i]); hit = true; // ^ Nice Touch! break; } if (!hit) SMS.Default.Index = SMS.Default.FileNames.Count -1; SMS.Default.Save(); Args = new string[0]; } #endregion Rev3 Parms Passed-in Handling. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region MultiSelect Method Group. /// Posted from a worker thread /// in SmesaMmfIpc.MmfServerSide lines 73 & 79. /// See: WindowsFormsSynchronizationContext /// v3.1.1.39 08-Mar-2018 integrated new method /// Also called from Smesa.OpenSelectedFiles on /// return from Preferences Object. /// /// private void MultiSelect(object files) { var args = files as Collection; if (args == null || args.Count < 2) return; var c = args.Count; var tab = Convert.ToInt32(args[c-1]); args.RemoveAt(c - 1); var cnt = args.Count; var ary = new string[cnt]; for (var i = 0; i < cnt; ++i) ary[i] = Convert.ToString(args[i]); MultiSelect(tab, ary, true); } /// First file goes into the /// current tab (TabPref already handled /// by TabPrompt() call in OpenClick() /// && MmfServerSide()) /// Then the rest go into new tabs we'll need /// to create. (All but the first one that is!) /// /// /// /// private void MultiSelect( int tab, string[] fnms, bool mmf = false) { if (!mmf) { ProgressBar1.Value = 49; var dir = Path.GetDirectoryName( SMS.Default.FileNames[ TabControl.SelectedIndex]); KeyDown -= SmesaKeyDown; fnms = FileNameGet(fnms, dir); KeyDown += SmesaKeyDown; } if (fnms.Length < 2) { SingleSelect(tab, fnms, true); return; } ProgressBar1.Value = 75; var was = SMS.Default.FileNames.Count; var files = new Collection(); foreach (var fn in fnms.Where(fn => !SMS.Default.FileNames.Contains(fn) && File.Exists(fn))) files.Add(fn); // Skip ^ duplicates and nonexistents. if (files.Count < 1) { NeverMind(); // <-= v67mods var ct = fnms.Length -1; // if all files are already open // then go to the last tab listed. for (var i = ct; i > -1; --i) { // v72mods vv if (!SMS.Default.FileNames .Contains(fnms[i])) continue; TabControl.SelectedIndex = SMS.Default.FileNames.IndexOf(fnms[i]); break; } return; } if (files.Count == 1) // bugg fixx SingleSelect(tab, new[]{files[0]}, true); else MultiSelect(was, tab, files); } private void NeverMind() { if (!_newTab) return; var last = TabControl.TabPages.Count -1; TabControl.SelectedIndex = last; TabClose(last); } private void MultiSelect( int was, int tab, IList files) { NotOpenYet(files[0], tab); // Get that ^ first one out of the way. var c = files.Count - 1; for (var i = 0; i < c; ++i) NewClick(); // minus ^ that one. var x = 0; // index zero above... #region NOTE // What was the count, now // becomes the starting index. // NOTE: loop starts at index = 1; #endregion NOTE for (var i = was; i < was + c; ++i) NotOpenYet(files[++x], i); for (var i = 0; i < SMS.Default .FileNames.Count; ++i) Editor(i, true, true); MultiSelect(tab); SMS.Default.BarValue[tab] = Convert.ToString("100"); SMS.Default.Save(); } private void MultiSelect(int tab) { TabControl.SelectedIndex = tab; #region Event ^ Note // ^ This li guy Triggers TabChange() event: // Then Editing and everything does the rest. // Makes sure the Filename is the Tab-text & // all that stuff, Colors per extension, etc. #endregion var rtb = TabControl.TabPages[tab] .Controls[_index] as RichTextBox; if (rtb == null) throw new ArgumentException( "MultiSelect(int)"); rtb.Focus(); rtb.SelectionStart = rtb.SelectionLength = 0; } #endregion MultiSelect Method Group. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region NewTabPage Related Code // If no Current Tabs in Settings it Defaults // to the Primary Tab & Empty RTB of Pref FileType. // App Comes with 1 tabPage in Design... // ...2nd TabPage & up are Added here. private void PreCreatePages() { if (!SMS.Default.MultiTab) return; var trash = new Collection(); for (var i = 1; i < SMS.Default .FileNames.Count; ++i) if (File.Exists( SMS.Default.FileNames[i])) NewClick(); else // Trash non existents. trash.Add(i); foreach (var i in trash) SMS.Default.FileNames.RemoveAt(i); SMS.Default.Save(); } private void NewClick (object sender, EventArgs e) { if (!SMS.Default.MultiTab && !YesNoDialog( SMR.NewClickText, SMR.NewClickTitle, 1)) return; SMS.Default.MultiTab = true; NewClick(); GetCharCount(null, true); } /// See GetNewRtb Html Below /// private void NewClick() { var tc = TabControl.TabPages.Count; var fn = GetDefaultFileName(tc); // Create New tabPage Object. TabControl.TabPages.Add(fn);// <-===<< // Name the new Tab TabControl.TabPages[tc].Name = string.Format("tabPage{0}", tc + 1); // SmeRtb Custom Control Project Instance. CreateRtb(tc); // Getta good handle on new tabPage's RTB. var rt = TabControl.TabPages[tc] .Controls[_index] as RichTextBox; if (rt == null) throw new ArgumentException("NewClick"); rt.ForeColor = NotText(tc) ? SMS.Default.SmeSelFore : MyCustomPrintLibrary .MyFontClass.MePrintColor; rt.Focus(); Validate(); } /// Works with NewClick /// There is already a Design-Time RichTextBox. /// Create Custom Control from a Copy of it /// to set the defaults we want. Grab a new /// instance of it during run-time. Then /// give it some of the Run-Time Properties, /// Give it a Unique Name and Add it to a New /// tabPage which is then added to the /// TabControl.TabPage[Collection]; /// Puts the Focus on it, etc, etc. /// v2.2.6.27 07-Jan-2018 /// /// private void CreateRtb(int tab) { // See MyCustomControl v Project. RichTextBox rtb; using (var cc = new CustomControl()) // <-= { rtb = cc.R1; } // ^ Using Free Garbage Disposal! if (rtb == null) throw new ArgumentException("CreateRtb1"); SyncRtb(tab, rtb); var test = TabControl .TabPages[tab].Controls[_index]; if (test == null) throw new ArgumentException("CreateRtb2"); // And Select this new Tab. Zoomed = true; TabControl.SelectedIndex = tab; #region Event ^ Note // ^ This li guy Triggers TabChange() event: // Then Editing and everything does the rest. // Makes sure the Filename is the Tab-text & // all that stuff, Colors per extension, etc. #endregion Zoomed = false; Check5(); // Bring ALL Collections up or down. } private void SyncRtb( int tc, RichTextBox rtb) { // Name the new Custom Control. rtb.Name = string.Format( "RichTextBox{0}", tc + 1); // Sync Certain Properties: var r1 = RichTextBox1; rtb.ZoomFactor = 1; rtb.Size = r1.Size; rtb.ContentsResized += Zoomer; rtb.ContextMenuStrip = ContextMenu1; rtb.WordWrap = r1.WordWrap; TabControl.TabPages[tc] .Controls.Add(rtb); } #endregion NewTabPage Related Code //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region MultiTab Related Code // v3.1.1.39 08-Mar-2018 private void TabPrompt() { _tab = TabPrompt( TabControl.SelectedIndex); } /// Legend: /// Choice = 1 ; New Tab /// Choice = 2 ; Current Tab /// Choice = 3 ; Cancel /// Choice = 4 ; New Tab Pref /// Choice = 5 ; Current Pref /// /// /// private int TabPrompt(int tab) { var choice = -1; if (SMS.Default.TabPrefSet) { if (!SMS.Default.TabPref) return tab; // item 5 choice = 4; } KeyDown -= SmesaKeyDown;// very cool! <-= if ( choice != 4) choice = MCD.NewTabPrompt(); // <-= Awesome! KeyDown += SmesaKeyDown; if (choice == 3) return -1; if (choice == 5 || choice == 2) { if (choice == 5) { SMS.Default.TabPrefSet = true; SMS.Default.TabPref = false; } return tab; } // Only choice 1 & 4 remain. if (choice == 4) { SMS.Default.TabPref = true; SMS.Default.TabPrefSet = true; } tab = TabControl.TabPages.Count; NewClick(); _newTab = true; return TabControl.SelectedIndex = tab; #region Event ^ Note // ^ This li guy Triggers TabChange() EVENT: // Then Editing and everything does the rest. // Makes sure the Filename is the Tab-text & // all that stuff, Colors per extension, etc. #endregion } private bool _newTab; private void CheckTabs(int tab) { var tpgs = TabControl.TabPages.Count; while (tpgs <= tab) { NewClick(); tpgs = TabControl.TabPages.Count; } } #endregion Multi Tab Pages Related Code //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Changed Tabs Related Code /// Wraps top to bottom or /// bottom to top of list if needed. /// /// /// private int CheckForWrap(int tab) { var c = TabControl.TabPages.Count; #region TestCode //if (tab < 0 || tab >= c // && SMS.Default.Testing) // MessageBox.Show(string.Format( // "Caught one!\n\nTab == {0}", tab)); #endregion TestCode if (tab < 0) tab = c - 1; if (tab >= c) tab = 0; return tab; } /// This event is before the Tab Change, /// and ChangedTabs(); is after this event here. /// Stores relevant data in case of return to /// this Tab from afar. /// /// /// private void PageDeselecting( object sender, TabControlCancelEventArgs e) { var tab = CheckForWrap( TabControl.SelectedIndex); var cnt = SMS.Default.BarValue.Count; var str = Convert.ToString( ProgressBar1.Value); if (tab < cnt) SMS.Default.BarValue[tab] = str; else SMS.Default.BarValue.Add(str); str = StatusLabel.Text; var c = SMS.Default.Status.Count; if (tab < c) SMS.Default.Status[tab] = str; else SMS.Default.Status.Add(str); SMS.Default.Save(); } // NOTE: Before Above, After Below. (extreme interaction) /// This is called AFTER the above /// whenever the User Clicks a different Tab. /// Then this Method brings back relevant /// data from Previous views of this /// tabPage, saved via the above. /// /// /// private void ChangedTabs (object sender, EventArgs e) { var t = TabControl.SelectedIndex; var r = TabControl.TabPages[t] .Controls[_index] as RichTextBox; if (r != null) r.Focus(); Editing(t < SMS.Default.FileNames.Count, false); ProgressBar1.Value = GetValue(t); SaveButtonHandler(t); // So Sweet! Zoomer(); Validate(); } private void SaveButtonHandler(int t) { var unsaved = CheckForSave(); if (unsaved.Count < 1) { SaveButton.Enabled = SaveAllButton.Enabled = false; SavedStatus(t); return; } SaveAllButton.Enabled = true; SaveButton.Enabled = unsaved.Contains(t); if (SaveButton.Enabled) UnSavedStatus(t); } private void SavedStatus(int tab) { var file = MCT.GetFile( tab, SMS.Default.FileNames, GetDefaultFileName(tab)); var status = string.Format( "Editing File: {0}", file); if (tab < SMS.Default.Status.Count) SMS.Default.Status[tab] = status; else SMS.Default.Status.Add(status); StatusLabel.Text = StatusLabel.ToolTipText = status; } private void UnSavedStatus(int tab) { const string s = " : "; var status = SMR.Status_Unsaved + s + MCT.GetFile( tab, SMS.Default.FileNames, GetDefaultFileName(tab)); if (tab < SMS.Default.Status.Count) SMS.Default.Status[tab] = status; else SMS.Default.Status.Add(status); StatusLabel.Text = StatusLabel.ToolTipText = status; Asterisk(tab); } // Add ^ asterisk to unsaved tab text. private void Asterisk(int tab) { var fn = Path.GetFileName( SMS.Default.FileNames[tab]); var tp = TabControl.TabPages[tab]; if (tp == null || TabControl .TabPages.Count < 1) throw new ArgumentException("Asterisk"); const string ast = "*"; tp.Text = fn + ast; } /// These are the ints /// you're looking for. Keep Moving. /// /// /// private int GetValue(int tab) { var value = 100; if (tab >= SMS.Default.BarValue.Count) SMS.Default.BarValue.Add("100"); try { value = Convert.ToInt32( SMS.Default.BarValue[tab]); } catch (ArgumentOutOfRangeException ex) { ChangedTabsCatcher(tab, Convert.ToString(ex)); } catch (FormatException ex) { ChangedTabsCatcher(tab, Convert.ToString(ex)); } catch (OverflowException ex) { ChangedTabsCatcher(tab, Convert.ToString(ex)); } SMS.Default.Save(); return value; } private void ChangedTabsCatcher( int t, string ex) { ProgressBar1.Value = 100; var c = SMS.Default.BarValue.Count; const string x = "100"; if (t < c) SMS.Default.BarValue[t] = x; else SMS.Default.BarValue.Add(x); SMS.Default.Save(); if (!MCT.Testing) return; var tx = string.Format( "Managed Exception in " + "Changed Tabs:\n\n{0}", ex); MessageBox.Show(tx); } #endregion Changed Tabs Related Code //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Shade or Unshade Both Save Buttons. /// Shade the Smesa SaveButton /// Icon in ToolBar and Check to /// see if Everything else is saved /// and if so Shade SaveAllButton too. /// private void ShadyMethod() { SavedStatus( TabControl.SelectedIndex); SaveButton.Enabled = false; if (CheckForSave().Count > 1) return; // If anything else needs Saved. SaveAllButton.Enabled = false; } /// UnShade Both SaveButton /// & SaveAllButton Icons in the ToolBar. /// UnShade SaveAll anytime even 1 is unsaved. /// private void UnshadyMethod() { UnSavedStatus( TabControl.SelectedIndex); SaveAllButton.Enabled = SaveButton.Enabled = true; } #endregion Shade or Unshade //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region RestoreEditors Related Code /// Open any Tabs and Files /// from the Last Run for this /// particular User in AppData. /// v4.5.9.63 11-Aug-2018 -JpE- /// private void SetupOpenFiles() { var dir = Path. GetDirectoryName(Mapped); dir = Path.GetDirectoryName(dir); dir = Path.GetDirectoryName(dir); dir += SMR.Res; #region testcode //MessageBox.Show(// testscode // string.Format( // "dir == {0}",dir)); #endregion string l = dir + SMR.Lic, a = dir + SMR.Abt, b = MCT.GetDocFolder, o = b + "\\" + Path.GetFileName(l), r = b + "\\" + Path.GetFileName(a); if ( !File.Exists(l) || !File.Exists(a)) { if (MCT.Testing) { MessageBox.Show(SMR.Err3); throw new ArgumentException("ME Err3"); } return; } File.Copy(l, o, true); Thread.Sleep(37); File.Copy(a, r, true); var f = SMS.Default.FileNames[0]; var u = SMS.Default.FileNames.Count; var n = true; if (string.IsNullOrEmpty(f) || u < 3){ if (u == 0 || u <= 2 && f.Contains(GetDefaultFileName(0)) || f.Contains(o) || f.Contains(r)){ n = false; // Welcome to MyEditor! SMS.Default.FileNames.Clear(); SMS.Default.FileNames.Add(r); SMS.Default.FileNames.Add(o); Editing(); } } u = SMS.Default.FileNames.Count; if (!SMS.Default.MultiTab) while (u > 1) SMS.Default .FileNames.RemoveAt(--u); SMS.Default.Save(); Check5(); SetupAllTabs(n); // v to simplify v } /// Create and Load Open Tabs /// from the Last Run by This User. /// Restore Previous Properties for /// each Editor-Window / Rtb. /// Final Rev2.2.6.27agate 07-Jan-2018 /// v4.5.9.63 11-Aug-2018 -JpE- /// private void SetupAllTabs(bool normal) { TabControl.SelectedIndex = 0; #region Event ^ Note // ^ This li guy Triggers TabChange() event: // Then Editing and everything does the rest. // Makes sure the Filename is the Tab-text & // all that stuff, Colors per extension, etc. #endregion var r = RichTextBox1; RichTextBox1.Focus(); if (!NotText(0)) SetupRtb4Txt(r); else SetupRtb4Rtf(r); // Rev2 creates tabPages 1st. var c = SMS.Default.FileNames.Count; if (c > 1) PreCreatePages(); if (c > 0) // <-= This may help! LoL for (var i = 0; i < c; ++i) LoadRtb(SMS.Default.FileNames[i], i); ProgressBar1.Value = 87; for (var i = 0; i < c; ++i) ZeroSaveMeItem(i); if (normal) RestoreEditors(); // else Welcome Files, About & License. // v4.6.9.68 10-Sep-2018 Editing(); // <-= Critical! } /// Restore Entire App Editors /// and Line Numbers & cursor position, /// etc back to state of previous run /// for that user. /// (called on form loading) /// private void RestoreEditors() { for (var i = 0; i < SMS.Default.FileNames.Count; ++i) { var tb = TabControl.TabPages[i]; if (tb == null) throw new ArgumentException("RestoreEditorTabs"); tb.Text = Path.GetFileName( SMS.Default.FileNames[i]); var rtb = tb.Controls[_index] as RichTextBox; if (rtb == null) throw new ArgumentException("RestoreEditors"); rtb.ZoomFactor = Convert.ToSingle( SMS.Default.Zoo[i]); var sel = MCT.PositionCursor( i, SMS.Default.Curses); var nums = sel.Split(','); int start, lngth; try { start = Convert.ToInt32(nums[0]); lngth = Convert.ToInt32(nums[1]); } catch (FormatException) { start = 0; lngth = 0; } catch (OverflowException) { start = 0; lngth = 0; } rtb.SelectionStart = start; rtb.SelectionLength = lngth; } } #endregion RestoreEditors Related Code //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ } }