/// <summary> /// Call this when changed an array element etc directly without assigning the array etc to a property. Else changes may be not saved. /// </summary> public void SaveLater() { #if TRACE_JS //if(_save == 0) AWarning.Write("JSettings.SaveLater", 1, "<>Trace: "); #endif Interlocked.Exchange(ref _save, 1); }
/// <summary> /// Adds a window trigger and its action. /// </summary> /// <exception cref="InvalidOperationException">Cannot add triggers after <c>Triggers.Run</c> was called, until it returns.</exception> public Action <WindowTriggerArgs> this[TWEvent winEvent, AWnd.Finder f, TWFlags flags = 0, TWLater later = 0] { set { _triggers.ThrowIfRunning_(); if (f.Props.contains.Value is AWinImage.Finder) { AWarning.Write("Window triggers with 'contains image' are unreliable."); } var t = new WindowTrigger(_triggers, value, winEvent, f, flags, later); ref var last = ref _tActive; if (t.IsVisible)
/// <summary> /// Calls <see cref="LoadImageFromString"/> and handles exceptions. On exception returns null and optionally writes warning to the output. /// </summary> public static Bitmap TryLoadImageFromString(string s, bool warning) { try { return(LoadImageFromString(s)); } catch (Exception ex) { if (warning) { AWarning.Write(ex.ToStringWithoutStack()); } } return(null); }
internal bool CallFunc(TriggerArgs args) { #if true if (_funcAfter != null) { try { foreach (var v in _funcAfter) { var t1 = ATime.PerfMilliseconds; bool ok = v.f(args); var td = ATime.PerfMilliseconds - t1; if (td > 200) { AWarning.Write($"Too slow Triggers.FuncOf function of a window trigger. Should be < 10 ms, now {td} ms. Task name: {ATask.Name}.", -1); } if (!ok) { return(false); } } } catch (Exception ex) { AOutput.Write(ex); return(false); } } #else for (int i = 0; i < 2; i++) { var af = i == 0 ? _funcBefore : _funcAfter; if (af != null) { foreach (var v in af) { bool ok = v.f(args); if (!ok) { return(false); } } } } #endif return(true); //SHOULDDO: measure time more intelligently, like in MatchScope, but maybe give more time. }
/// <summary> /// Writes s + "\r\n" and optionally timestamp. /// </summary> /// <remarks> /// If fails to write to file: Sets LogFile=null, which closes file handle. Writes a warning and s to the output window or console. /// </remarks> public bool WriteLine(string s) { bool ok; int n = Encoding.UTF8.GetByteCount(s ??= "") + 1; fixed(byte *b = Util.AMemoryArray.Byte_(n + 35)) { if (LogFileTimestamp) { Api.GetLocalTime(out var t); Api.wsprintfA(b, "%i-%02i-%02i %02i:%02i:%02i.%03i ", __arglist(t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond, t.wMilliseconds)); int nn = Util.BytePtr_.Length(b); Encoding.UTF8.GetBytes(s, new Span <byte>(b + nn, n)); n += nn; if (s.Starts("<>")) { Api.memmove(b + 2, b, nn); b[0] = (byte)'<'; b[1] = (byte)'>'; } } else { Encoding.UTF8.GetBytes(s, new Span <byte>(b, n)); } b[n - 1] = 13; b[n++] = 10; ok = Api.WriteFile(_h, b, n, out _); } if (!ok) { string emsg = ALastError.Message; LogFile = null; AWarning.Write($"Failed to write to log file '{_name}'. {emsg}"); WriteDirectly(s); //Debug.Assert(false); } return(ok); }
public static void Init() { //using var p = APerf.Create(); //map command handler names/delegates etc _cmd = new CmdHandlers(); //p.Next(); //ADebug.MemorySetAnchor_(); _strips = new AuStripManager(Program.MainForm, _cmd); _strips.BuildAll(AFolders.ThisAppBS + @"Default\Strips.xml", ProgramSettings.DirBS + "Strips.xml", new AuDockPanel.ZDockedToolStripRenderer()); //ADebug.MemoryPrint_(); //p.Next(); //get top-level toolstrips (menu bar and toolbars) Menubar = _strips.MenuBar; tbFile = _strips.Toolbars["File"]; tbEdit = _strips.Toolbars["Edit"]; tbRun = _strips.Toolbars["Run"]; tbTools = _strips.Toolbars["Tools"]; tbHelp = _strips.Toolbars["Help"]; tbCustom1 = _strips.Toolbars["Custom1"]; tbCustom2 = _strips.Toolbars["Custom2"]; //get submenus that will be filled later or used separately etc (ddFileNew = _strips.Submenus["File_New"]).Opening += (o, e) => Panels.Files.ZFillMenuNew(o as ToolStripDropDownMenu); _strips.Submenus["File_RecentWorkspaces"].Opening += (o, e) => Panels.Files.ZFillMenuRecentWorkspaces(o as ToolStripDropDownMenu); _strips.Submenus["Tools_Panels"].Opening += (se, da) => Panels.PanelManager.ZAddShowPanelsToMenu(se as ToolStripDropDown, false, true); _strips.Submenus["Tools_Toolbars"].Opening += (se, da) => Panels.PanelManager.ZAddShowPanelsToMenu(se as ToolStripDropDown, true, true); ddFile = _strips.Submenus["Menu_File"]; ddEdit = _strips.Submenus["Menu_Edit"]; ddOutput = _strips.Submenus["Tools_Output"]; //ddStatusBar = _strips.Submenus["Tools_StatusBar"]; //get controls cHelpFind = tbHelp.Items["Help_Find"] as ToolStripSpringTextBox; //var cw1 = new ComboWrapper(cHelpFind.Control); //cw1.ArrowButtonPressed += (unu, sed) => AOutput.Write("not implemented"); cHelpFind.Visible = false; //FUTURE //p.NW(); //make some buttons wider int wider = Au.Util.ADpi.ScaleInt(5); tbRun.Items["Run_Run"].Padding = new Padding(wider, 0, wider, 0); //tbHelp.Padding = new Padding(); //removes 1-pixel right margin that causes a visual artifact because of gradient, but then not good when no margin when the edit is at the very right edge of the form #if DEBUG //all commands have menu items? //var p = APerf.Create(); foreach (var k in _cmd.Dict.Keys) { //AOutput.Write(k); if (_strips.Xml.Desc(k) == null) { AWarning.Write("no menu item for command " + k); } } //p.NW(); //450 //for vice versa, AuStripManager takes care #endif #if TRACE //tbCustom2.Items.Add("Test", null, TestCompiler.Test); tbCustom2.Items.Add("Test", null, (unu, sed) => { Program.MainForm.TestEditor(); //Panels.Files.Test(); //Panels.Editor.Test(); //Program.Model.LoadState(); //TestCompiler.TestCompiling(); //TestCompiler.TestParsing(); }); #endif }
static void _OutOfMemory() { AWarning.Write("There is not enough memory available to start the trigger action thread.", -1); //info: -1 because would need much memory for stack trace }
//Loads and parses XML. Creates the _aX lists, _firstSplit and the tree structure. void _LoadXmlAndCreateLayout(string xmlFileDefault, string xmlFileCustomized) { //We have 1 or 2 XML files containing panel/toolbar layout. //xmlFileDefault contains default XML. It eg can be in AFolders.ThisApp. //xmlFileCustomized contains previously saved XML (user-modified layout). //At first try to load xmlFileCustomized. If it does not exist or is invalid, load xmlFileDefault; or get missing data from xmlFileDefault, if possible. //Also loads xmlFileDefault when xmlFileCustomized XML does not match panels of new app version and cannot resolve it (eg some panels removed). bool usesDefaultXML = false; string xmlFile = xmlFileCustomized, xmlVersion = null, outInfo = null; for (int i = 0; i < 2; i++) { if (i == 0) { if (!AFile.ExistsAsFile(xmlFile)) { continue; } } else { usesDefaultXML = true; xmlFile = xmlFileDefault; } bool fileLoaded = false; try { var x = AExtXml.LoadElem(xmlFile); fileLoaded = true; if (!usesDefaultXML) { xmlVersion = x.Attr("version"); } x = x.Element("split"); //THIS DOES THE MAIN JOB _firstSplit = new _Split(this, null, x); if (_aPanel.Count < _initControls.Count) //more panels added in this app version { if (usesDefaultXML) { throw new Exception("debug1"); } _GetPanelXmlFromDefaultFile(xmlFileDefault); } break; //speed: xml.Load takes 170 microseconds. //tested: XML can be added to Application Settings, but var xml=Properties.Settings.Default.PanelsXML takes 61 MILLIseconds. } catch (Exception e) { var sErr = $"Failed to load file '{xmlFile}'.\r\n\t{e.ToStringWithoutStack()}"; if (usesDefaultXML) { _xmlFile = null; ADialog.ShowError("Cannot load panel/toolbar layout.", $"{sErr}\r\n\r\nReinstall the application."); Environment.Exit(1); } else { //probably in this version there are less panels, most likely when downgraded. Or the file is corrupt. if (fileLoaded && xmlVersion != _asmVersion) { outInfo = "Info: this application version resets the panel/toolbar layout, sorry."; } else { AWarning.Write(sErr, -1); } } _aSplit.Clear(); _aTab.Clear(); _aPanel.Clear(); } } //if(usesDefaultXML || xmlVersion == _asmVersion) return; if (outInfo != null) { AOutput.Write(outInfo); } }