Merge pull request #2781 from jlewin/design_tools

Revise startup
This commit is contained in:
johnlewin 2017-12-18 22:20:43 -08:00 committed by GitHub
commit a1f2d2e94a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 1030 additions and 899 deletions

View file

@ -139,7 +139,7 @@ namespace MatterHackers.MatterControl
linkButton.OriginRelativeParent = new VectorMath.Vector2(linkButton.OriginRelativeParent.X, linkButton.OriginRelativeParent.Y + descentInPixels);
linkButton.Click += (sender, mouseEvent) =>
{
MatterControlApplication.Instance.LaunchBrowser(elementState.Href);
ApplicationController.Instance.LaunchBrowser(elementState.Href);
};
elementsUnderConstruction.Peek().AddChild(linkButton);
}
@ -196,7 +196,7 @@ namespace MatterHackers.MatterControl
linkButton.Cursor = Cursors.Hand;
linkButton.Click += (sender, mouseEvent) =>
{
MatterControlApplication.Instance.LaunchBrowser(elementState.Href);
ApplicationController.Instance.LaunchBrowser(elementState.Href);
};
elementsUnderConstruction.Peek().AddChild(linkButton);
}

View file

@ -239,7 +239,7 @@ namespace MatterHackers.MatterControl
{
InitiateUpdateDownload();
// Switch to the about page so we can see the download progress.
GuiWidget aboutTabWidget = FindNamedWidgetRecursive(ApplicationController.Instance.MainView, "About Tab");
GuiWidget aboutTabWidget = ApplicationController.Instance.MainView.FindNamedChildRecursive("About Tab");
if (aboutTabWidget is Tab aboutTab)
{
@ -248,25 +248,6 @@ namespace MatterHackers.MatterControl
}
}
private static GuiWidget FindNamedWidgetRecursive(GuiWidget root, string name)
{
foreach (GuiWidget child in root.Children)
{
if (child.Name == name)
{
return child;
}
GuiWidget foundWidget = FindNamedWidgetRecursive(child, name);
if (foundWidget != null)
{
return foundWidget;
}
}
return null;
}
private void onVersionRequestFailed(object sender, ResponseErrorEventArgs e)
{
SetUpdateStatus(UpdateStatusStates.UpToDate);
@ -455,7 +436,7 @@ namespace MatterHackers.MatterControl
installUpdate.Start();
//Attempt to close current application
SystemWindow topSystemWindow = MatterControlApplication.Instance as SystemWindow;
SystemWindow topSystemWindow = AppContext.RootSystemWindow;
if (topSystemWindow != null)
{
topSystemWindow.CloseOnIdle();

View file

@ -69,6 +69,21 @@ namespace MatterHackers.MatterControl
using MatterHackers.VectorMath;
using SettingsManagement;
public class AppContext
{
/// <summary>
/// Native platform features
/// </summary>
public static INativePlatformFeatures Platform { get; set; }
public static bool IsLoading { get; internal set; } = true;
/// <summary>
/// The root SystemWindow
/// </summary>
public static SystemWindow RootSystemWindow { get; internal set; }
}
public class ApplicationController
{
public ThemeConfig Theme { get; set; } = new ThemeConfig();
@ -109,10 +124,7 @@ namespace MatterHackers.MatterControl
public const string EnvironmentName = "";
#endif
/// <summary>
/// Allows application components to hook initial SystemWindow Load event without an existing Widget instance
/// </summary>
public static event EventHandler Load;
public bool ApplicationExiting { get; internal set; } = false;
public static Func<string, Task<Dictionary<string, string>>> GetProfileHistory;
@ -145,7 +157,7 @@ namespace MatterHackers.MatterControl
// HACK: short term solution to resolve printer reference for non-printer related contexts
DragDropData.Printer = printer;
if (!MatterControlApplication.IsLoading)
if (!AppContext.IsLoading)
{
// Fire printer changed event
}
@ -161,7 +173,7 @@ namespace MatterHackers.MatterControl
ActiveSliceSettings.OnActivePrinterChanged(null);
}
if (!MatterControlApplication.IsLoading
if (!AppContext.IsLoading
&& printer.Settings.PrinterSelected
&& printer.Settings.GetValue<bool>(SettingsKey.auto_connect))
{
@ -178,6 +190,13 @@ namespace MatterHackers.MatterControl
{
await this.SetActivePrinter(emptyPrinter);
}
public void LaunchBrowser(string targetUri)
{
UiThread.RunOnIdle(() =>
{
Process.Start(targetUri);
});
}
public void RefreshActiveInstance(PrinterSettings updatedPrinterSettings)
{
@ -224,7 +243,7 @@ namespace MatterHackers.MatterControl
{
Thread.CurrentThread.Name = $"ThumbnailGeneration";
while(!MatterControlApplication.Instance.ApplicationExiting)
while(!this.ApplicationExiting)
{
Thread.Sleep(100);
@ -273,7 +292,7 @@ namespace MatterHackers.MatterControl
public SlicePresetsWindow EditQualityPresetsWindow { get; set; }
public ApplicationView MainView;
public GuiWidget MainView;
private EventHandler unregisterEvents;
@ -476,19 +495,18 @@ namespace MatterHackers.MatterControl
ScrollBar.ScrollBarWidth = 8 * GuiWidget.DeviceScale;
ScrollBar.GrowThumbBy = 2;
// Initialize statics
DefaultThumbBackground.DefaultBackgroundColor = Color.Transparent;
Object3D.AssetsPath = ApplicationDataStorage.Instance.LibraryAssetsPath;
this.Library = new LibraryConfig();
this.Library.ContentProviders.Add(new[] { "stl", "obj", "amf", "mcx" }, new MeshContentProvider());
this.Library.ContentProviders.Add("gcode", new GCodeContentProvider());
// Name = "MainSlidePanel";
ActiveTheme.ThemeChanged.RegisterEvent((s, e) =>
{
if (!MatterControlApplication.IsLoading)
if (!AppContext.IsLoading)
{
ReloadAll();
}
@ -679,7 +697,7 @@ namespace MatterHackers.MatterControl
VAnchor = VAnchor.Center
});
MatterControlApplication.Instance.AddChild(reloadingOverlay);
AppContext.RootSystemWindow.AddChild(reloadingOverlay);
this.IsReloading = true;
@ -687,19 +705,17 @@ namespace MatterHackers.MatterControl
{
using (new QuickTimer($"ReloadAll_{reloadCount++}:"))
{
MainView?.CloseAllChildren();
using (new QuickTimer("ReloadAll_AddElements"))
{
// Actual ReloadAll implementation
MainView?.CreateAndAddChildren();
}
MainView = new WidescreenPanel();
this.DoneReloadingAll?.CallEvents(null, null);
using (new QuickTimer("Time to AddMainview: "))
{
AppContext.RootSystemWindow.CloseAllChildren();
AppContext.RootSystemWindow.AddChild(MainView);
}
}
this.IsReloading = false;
MatterControlApplication.Instance.RemoveChild(reloadingOverlay);
});
}
@ -720,7 +736,7 @@ namespace MatterHackers.MatterControl
ApplicationSettings.Instance.ReleaseClientToken();
}
static void LoadOemOrDefaultTheme()
internal static void LoadOemOrDefaultTheme()
{
// if not check for the oem color and use it if set
// else default to "Blue - Light"
@ -741,26 +757,15 @@ namespace MatterHackers.MatterControl
{
if (globalInstance == null)
{
//using (new PerformanceTimer("Startup", "AppController Instance"))
globalInstance = new ApplicationController();
ActiveSliceSettings.ActivePrinterChanged.RegisterEvent((s, e) =>
{
globalInstance = new ApplicationController();
// Set the default theme colors
LoadOemOrDefaultTheme();
// Accessing any property on ProfileManager will run the static constructor and spin up the ProfileManager instance
bool na = ProfileManager.Instance.IsGuestProfile;
globalInstance.MainView = new DesktopView();
ActiveSliceSettings.ActivePrinterChanged.RegisterEvent((s, e) =>
if (!AppContext.IsLoading)
{
if (!MatterControlApplication.IsLoading)
{
ApplicationController.Instance.ReloadAll();
}
}, ref globalInstance.unregisterEvents);
}
ApplicationController.Instance.ReloadAll();
}
}, ref globalInstance.unregisterEvents);
}
return globalInstance;
}
@ -781,6 +786,12 @@ namespace MatterHackers.MatterControl
return string.IsNullOrEmpty(libraryItem.ID) ? null : ApplicationController.CacheablePath("ItemThumbnails", $"{libraryItem.ID}.png");
}
public string ThumbnailCachePath(ILibraryItem libraryItem, int width, int height)
{
// TODO: Use content SHA
return string.IsNullOrEmpty(libraryItem.ID) ? null : ApplicationController.CacheablePath("ItemThumbnails", $"{libraryItem.ID}-{width}x{height}.png");
}
public void SwitchToPurchasedLibrary()
{
var purchasedContainer = Library.RootLibaryContainer.ChildContainers.Where(c => c.ID == "LibraryProviderPurchasedKey").FirstOrDefault();
@ -791,6 +802,72 @@ namespace MatterHackers.MatterControl
}
}
public void OnLoadActions()
{
// TODO: Calling UserChanged seems wrong. Load the right user before we spin up controls, rather than after
// Pushing this after load fixes that empty printer list
/////////////////////ApplicationController.Instance.UserChanged();
bool showAuthWindow = PrinterSetup.ShouldShowAuthPanel?.Invoke() ?? false;
if (showAuthWindow)
{
if (ApplicationSettings.Instance.get(ApplicationSettingsKey.SuppressAuthPanel) != "True")
{
//Launch window to prompt user to sign in
UiThread.RunOnIdle(() => DialogWindow.Show(PrinterSetup.GetBestStartPage()));
}
}
else
{
//If user in logged in sync before checking to prompt to create printer
if (ApplicationController.SyncPrinterProfiles == null)
{
RunSetupIfRequired();
}
else
{
ApplicationController.SyncPrinterProfiles.Invoke("ApplicationController.OnLoadActions()", null).ContinueWith((task) =>
{
RunSetupIfRequired();
});
}
}
// TODO: This should be moved into the splash screen and shown instead of MainView
if (AggContext.OperatingSystem == OSType.Android)
{
// show this last so it is on top
if (UserSettings.Instance.get("SoftwareLicenseAccepted") != "true")
{
UiThread.RunOnIdle(() => DialogWindow.Show<LicenseAgreementPage>());
}
}
if (ApplicationController.Instance.ActivePrinter is PrinterConfig printer
&& printer.Settings.PrinterSelected
&& printer.Settings.GetValue<bool>(SettingsKey.auto_connect))
{
UiThread.RunOnIdle(() =>
{
//PrinterConnectionAndCommunication.Instance.HaltConnectionThread();
printer.Connection.Connect();
}, 2);
}
//HtmlWindowTest();
AppContext.IsLoading = false;
}
private static void RunSetupIfRequired()
{
if (!ProfileManager.Instance.ActiveProfiles.Any())
{
// Start the setup wizard if no profiles exist
UiThread.RunOnIdle(() => DialogWindow.Show(PrinterSetup.GetBestStartPage()));
}
}
public void SwitchToSharedLibrary()
{
// Switch to the shared library
@ -840,67 +917,6 @@ namespace MatterHackers.MatterControl
}
}
public void OnLoadActions()
{
Load?.Invoke(this, null);
// Pushing this after load fixes that empty printer list
ApplicationController.Instance.UserChanged();
bool showAuthWindow = PrinterSetup.ShouldShowAuthPanel?.Invoke() ?? false;
if (showAuthWindow)
{
if (ApplicationSettings.Instance.get(ApplicationSettingsKey.SuppressAuthPanel) != "True")
{
//Launch window to prompt user to sign in
UiThread.RunOnIdle(() => DialogWindow.Show(PrinterSetup.GetBestStartPage()));
}
}
else
{
//If user in logged in sync before checking to prompt to create printer
if (ApplicationController.SyncPrinterProfiles == null)
{
RunSetupIfRequired();
}
else
{
ApplicationController.SyncPrinterProfiles.Invoke("ApplicationController.OnLoadActions()", null).ContinueWith((task) =>
{
RunSetupIfRequired();
});
}
}
if (AggContext.OperatingSystem == OSType.Android)
{
// show this last so it is on top
if (UserSettings.Instance.get("SoftwareLicenseAccepted") != "true")
{
UiThread.RunOnIdle(() => DialogWindow.Show<LicenseAgreementPage>());
}
}
if (this.ActivePrinter.Settings.PrinterSelected
&& this.ActivePrinter.Settings.GetValue<bool>(SettingsKey.auto_connect))
{
UiThread.RunOnIdle(() =>
{
//PrinterConnectionAndCommunication.Instance.HaltConnectionThread();
this.ActivePrinter.Connection.Connect();
}, 2);
}
}
private static void RunSetupIfRequired()
{
if (!ProfileManager.Instance.ActiveProfiles.Any())
{
// Start the setup wizard if no profiles exist
UiThread.RunOnIdle(() => DialogWindow.Show(PrinterSetup.GetBestStartPage()));
}
}
private EventHandler unregisterEvent;
public Stream LoadHttpAsset(string url)
@ -1466,4 +1482,186 @@ namespace MatterHackers.MatterControl
});
}
}
public enum ReportSeverity2 { Warning, Error }
public interface INativePlatformFeatures
{
event EventHandler PictureTaken;
void TakePhoto(string imageFileName);
void OpenCameraPreview();
void PlaySound(string fileName);
void ConfigureWifi();
bool CameraInUseByExternalProcess { get; set; }
bool IsNetworkConnected();
void FindAndInstantiatePlugins(SystemWindow systemWindow);
void ProcessCommandline();
void ReportException(Exception e, string key = "", string value = "", ReportSeverity2 warningLevel = ReportSeverity2.Warning);
void PlatformInit(Action<string> reporter);
}
public static class Application
{
private static ProgressBar progressBar;
private static TextWidget statusText;
private static FlowLayoutWidget progressPanel;
private static string lastSection = "";
private static Stopwatch timer;
public static string PlatformFeaturesProvider { get; set; } = "MatterHackers.MatterControl.WindowsPlatformsFeatures, MatterControl";
public static SystemWindow LoadRootWindow(int width, int height)
{
timer = Stopwatch.StartNew();
var systemWindow = new RootSystemWindow(width, height)
{
BackgroundColor = Color.DarkGray
};
var overlay = new GuiWidget();
overlay.AnchorAll();
systemWindow.AddChild(overlay);
progressPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
{
HAnchor = HAnchor.Center,
VAnchor = VAnchor.Center,
MinimumSize = new VectorMath.Vector2(400, 100),
};
overlay.AddChild(progressPanel);
progressPanel.AddChild(statusText = new TextWidget("", textColor: new Color("#bbb"))
{
MinimumSize = new VectorMath.Vector2(200, 30)
});
progressPanel.AddChild(progressBar = new ProgressBar()
{
FillColor = new Color("#3D4B72"),
BorderColor = new Color("#777"),
Height = 11,
Width = 300,
HAnchor = HAnchor.Absolute,
VAnchor = VAnchor.Absolute
});
AppContext.RootSystemWindow = systemWindow;
// Hook SystemWindow load and spin up MatterControl once we've hit first draw
systemWindow.Load += (s, e) =>
{
ReportStartupProgress(0.02, "First draw->RunOnIdle");
//UiThread.RunOnIdle(() =>
Task.Run(() =>
{
ReportStartupProgress(0.1, "Datastore");
Datastore.Instance.Initialize();
ReportStartupProgress(0.15, "MatterControlApplication.Initialize");
var mainView = Initialize(systemWindow, (progress0To1, status) =>
{
ReportStartupProgress(0.2 + progress0To1 * 0.7, status);
});
ReportStartupProgress(0.9, "AddChild->MainView");
systemWindow.AddChild(mainView, 0);
ReportStartupProgress(1, "");
systemWindow.BackgroundColor = Color.Transparent;
overlay.Close();
// TODO: Still can't figure out the delay between concluding this block and the first actual render with MainView content. Current
// best guess is delays between widget construction and OpenGL texture creation
});
};
// Block indefinitely
ReportStartupProgress(0, "ShowAsSystemWindow");
return systemWindow;
}
public static GuiWidget Initialize(SystemWindow systemWindow, Action<double, string> reporter)
{
AppContext.Platform = AggContext.CreateInstanceFrom<INativePlatformFeatures>(PlatformFeaturesProvider);
reporter?.Invoke(0.01, "PlatformInit");
AppContext.Platform.PlatformInit((status) =>
{
reporter?.Invoke(0.01, status);
});
// TODO: Appears to be unused and should be removed
// set this at startup so that we can tell next time if it got set to true in close
UserSettings.Instance.Fields.StartCount = UserSettings.Instance.Fields.StartCount + 1;
reporter?.Invoke(0.05, "ApplicationController");
var na = ApplicationController.Instance;
// Set the default theme colors
reporter?.Invoke(0.1, "LoadOemOrDefaultTheme");
ApplicationController.LoadOemOrDefaultTheme();
// Accessing any property on ProfileManager will run the static constructor and spin up the ProfileManager instance
reporter?.Invoke(0.2, "ProfileManager");
bool na2 = ProfileManager.Instance.IsGuestProfile;
reporter?.Invoke(0.3, "MainView");
ApplicationController.Instance.MainView = new WidescreenPanel();
// now that we are all set up lets load our plugins and allow them their chance to set things up
reporter?.Invoke(0.8, "Plugins");
AppContext.Platform.FindAndInstantiatePlugins(systemWindow);
if (ApplicationController.Instance.PluginsLoaded != null)
{
ApplicationController.Instance.PluginsLoaded.CallEvents(null, null);
}
reporter?.Invoke(0.9, "Process Commandline");
AppContext.Platform.ProcessCommandline();
reporter?.Invoke(0.91, "OnLoadActions");
ApplicationController.Instance.OnLoadActions();
UiThread.RunOnIdle(CheckOnPrinter);
return ApplicationController.Instance.MainView;
}
private static void ReportStartupProgress(double progress0To1, string section)
{
UiThread.RunOnIdle(() =>
{
statusText.Text = section;
progressBar.RatioComplete = progress0To1;
progressPanel.Invalidate();
Console.WriteLine($"Time to '{lastSection}': {timer.ElapsedMilliseconds}");
timer.Restart();
lastSection = section;
});
}
private static void CheckOnPrinter()
{
try
{
// TODO: UiThread should not be driving anything in Printer.Connection
ApplicationController.Instance.ActivePrinter.Connection.OnIdle();
}
catch (Exception e)
{
Debug.Print(e.Message);
GuiWidget.BreakInDebugger();
#if DEBUG
throw e;
#endif
}
UiThread.RunOnIdle(CheckOnPrinter);
}
}
}

View file

@ -1,5 +1,5 @@
/*
Copyright (c) 2015, Lars Brubaker
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -28,13 +28,7 @@ either expressed or implied, of the FreeBSD Project.
*/
using System.Collections.Generic;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl.CustomWidgets;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.VectorMath;
using System;
namespace MatterHackers.MatterControl
{
@ -49,40 +43,4 @@ namespace MatterHackers.MatterControl
public string ShortProfileID { get; set; }
public string CacheKey => this.ShortProfileID + ProfileManager.ProfileExtension;
}
public abstract class ApplicationView : GuiWidget
{
public abstract void CreateAndAddChildren();
}
public class DesktopView : ApplicationView
{
private WidescreenPanel widescreenPanel;
public DesktopView()
{
CreateAndAddChildren();
this.AnchorAll();
}
public override void CreateAndAddChildren()
{
this.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
var container = new FlowLayoutWidget(FlowDirection.TopToBottom);
container.AnchorAll();
GuiWidget.TouchScreenMode = UserSettings.Instance.IsTouchScreen;
container.AddChild(new HorizontalLine(alpha:50));
widescreenPanel = new WidescreenPanel();
container.AddChild(widescreenPanel);
using (new PerformanceTimer("ReloadAll", "AddChild"))
{
this.AddChild(container);
}
}
}
}

View file

@ -439,7 +439,7 @@ namespace MatterHackers.MatterControl
if (this.Scene.Persistable)
{
this.Scene.PersistAssets(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, progress);
this.EditContext.Save();
this.EditContext?.Save();
}
}
}

View file

@ -51,6 +51,7 @@ namespace MatterHackers.MatterControl
this.AnchorAll();
this.Name = "WidescreenPanel";
this.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
var theme = ApplicationController.Instance.Theme;

View file

@ -0,0 +1,179 @@
/*
Copyright (c) 2017, Lars Brubaker, John Lewin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Collections.Generic;
using System.IO;
using MatterHackers.Agg;
using MatterHackers.Agg.UI;
namespace MatterHackers.MatterControl
{
using Agg.Image;
using MatterHackers.Agg.Platform;
using MatterHackers.DataConverters3D;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PluginSystem;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.RenderOpenGl.OpenGl;
public class WindowsPlatformsFeatures : INativePlatformFeatures
{
public bool CameraInUseByExternalProcess { get; set; } = false;
public event EventHandler PictureTaken;
public void TakePhoto(string imageFileName)
{
ImageBuffer noCameraImage = new ImageBuffer(640, 480);
Graphics2D graphics = noCameraImage.NewGraphics2D();
graphics.Clear(Color.White);
graphics.DrawString("No Camera Detected", 320, 240, pointSize: 24, justification: Agg.Font.Justification.Center);
graphics.DrawString(DateTime.Now.ToString(), 320, 200, pointSize: 12, justification: Agg.Font.Justification.Center);
AggContext.ImageIO.SaveImageData(imageFileName, noCameraImage);
PictureTaken?.Invoke(null, null);
}
public void OpenCameraPreview()
{
//Camera launcher placeholder (KP)
if (ApplicationSettings.Instance.get(ApplicationSettingsKey.HardwareHasCamera) == "true")
{
//Do something
}
else
{
//Do something else (like show warning message)
}
}
public void PlaySound(string fileName)
{
if (AggContext.OperatingSystem == OSType.Windows)
{
using (var mediaStream = AggContext.StaticData.OpenSteam(Path.Combine("Sounds", fileName)))
{
(new System.Media.SoundPlayer(mediaStream)).Play();
}
}
}
public bool IsNetworkConnected()
{
return true;
}
public void ConfigureWifi()
{
}
public void FindAndInstantiatePlugins(SystemWindow systemWindow)
{
string oemName = ApplicationSettings.Instance.GetOEMName();
foreach (MatterControlPlugin plugin in PluginFinder.CreateInstancesOf<MatterControlPlugin>())
{
string pluginInfo = plugin.GetPluginInfoJSon();
Dictionary<string, string> nameValuePairs = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(pluginInfo);
if (nameValuePairs != null && nameValuePairs.ContainsKey("OEM"))
{
if (nameValuePairs["OEM"] == oemName)
{
plugin.Initialize(systemWindow);
}
}
else
{
plugin.Initialize(systemWindow);
}
}
}
public void ProcessCommandline()
{
var commandLineArgs = Environment.GetCommandLineArgs();
for (int currentCommandIndex = 0; currentCommandIndex < commandLineArgs.Length; currentCommandIndex++)
{
string command = commandLineArgs[currentCommandIndex];
string commandUpper = command.ToUpper();
switch (commandUpper)
{
case "FORCE_SOFTWARE_RENDERING":
GL.HardwareAvailable = false;
break;
case "CLEAR_CACHE":
AboutWidget.DeleteCacheData(0);
break;
case "SHOW_MEMORY":
RootSystemWindow.ShowMemoryUsed = true;
break;
}
}
// TODO: Do we still want to support command line arguments for adding to the queue?
foreach (string arg in commandLineArgs)
{
string argExtension = Path.GetExtension(arg).ToUpper();
if (argExtension.Length > 1
&& MeshFileIo.ValidFileExtensions().Contains(argExtension))
{
QueueData.Instance.AddItem(new PrintItemWrapper(new PrintItem(Path.GetFileName(arg), Path.GetFullPath(arg))));
}
}
}
public void ReportException(Exception e, string key = "", string value = "", ReportSeverity2 warningLevel = ReportSeverity2.Warning)
{
}
public void PlatformInit(Action<string> reporter)
{
if (AggContext.OperatingSystem == OSType.Mac && AggContext.StaticData == null)
{
// Set working directory - this duplicates functionality in Main but is necessary on OSX as Main fires much later (after the constructor in this case)
// resulting in invalid paths due to path tests running before the working directory has been overridden. Setting the value before initializing StaticData
// works around this architectural difference.
Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));
}
// Initialize a standard file system backed StaticData provider
if (AggContext.StaticData == null) // it may already be initialized by tests
{
AggContext.StaticData = new FileSystemStaticData();
}
ApplicationSettings.Instance.set("HardwareHasCamera", "false");
}
}
}

View file

@ -68,7 +68,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage
var previewButton = buttonFactory.Generate("Preview".Localize().ToUpper());
previewButton.Click += (s, e) =>
{
MatterControlApplication.Instance.OpenCameraPreview();
AppContext.Platform.OpenCameraPreview();
};
this.AddSettingsRow(
@ -286,11 +286,11 @@ namespace MatterHackers.MatterControl.ConfigurationPage
}
#endif
AddMenuItem("Forums".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("https://forums.matterhackers.com/category/20/mattercontrol"));
AddMenuItem("Wiki".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("http://wiki.mattercontrol.com"));
AddMenuItem("Guides and Articles".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("http://www.matterhackers.com/topic/mattercontrol"));
AddMenuItem("Release Notes".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("http://wiki.mattercontrol.com/Release_Notes"));
AddMenuItem("Report a Bug".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("https://github.com/MatterHackers/MatterControl/issues"));
AddMenuItem("Forums".Localize(), () => ApplicationController.Instance.LaunchBrowser("https://forums.matterhackers.com/category/20/mattercontrol"));
AddMenuItem("Wiki".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://wiki.mattercontrol.com"));
AddMenuItem("Guides and Articles".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://www.matterhackers.com/topic/mattercontrol"));
AddMenuItem("Release Notes".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://wiki.mattercontrol.com/Release_Notes"));
AddMenuItem("Report a Bug".Localize(), () => ApplicationController.Instance.LaunchBrowser("https://github.com/MatterHackers/MatterControl/issues"));
var updateMatterControl = new SettingsItem("Check For Update".Localize());
updateMatterControl.Click += (s, e) =>
@ -427,32 +427,6 @@ namespace MatterHackers.MatterControl.ConfigurationPage
private string rebuildThumbnailsMessage = "You are switching to a different thumbnail rendering mode. If you want, your current thumbnails can be removed and recreated in the new style. You can switch back and forth at any time. There will be some processing overhead while the new thumbnails are created.\n\nDo you want to rebuild your existing thumbnails now?".Localize();
private string rebuildThumbnailsTitle = "Rebuild Thumbnails Now".Localize();
private void RestartApplication()
{
UiThread.RunOnIdle(() =>
{
// Iterate to the top SystemWindow
GuiWidget parent = this;
while (parent.Parent != null)
{
parent = parent.Parent;
}
// MatterControlApplication is the root child on the SystemWindow object
MatterControlApplication app = parent.Children[0] as MatterControlApplication;
#if !__ANDROID__
app.RestartOnClose = true;
app.Close();
#else
// Re-initialize and load
LocalizedString.ResetTranslationMap();
ApplicationController.Instance.MainView = new DesktopView();
app.RemoveAllChildren();
app.AnchorAll();
#endif
});
}
[Conditional("DEBUG")]
private void GenerateLocalizationValidationFile()
{

View file

@ -82,7 +82,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
if (listView.ActiveContainer.Parent != null)
{
UiThread.RunOnIdle(() => listView.LoadContainer(listView.ActiveContainer.Parent));
UiThread.RunOnIdle(() => listView.SetActiveContainer(listView.ActiveContainer.Parent));
}
};
@ -119,7 +119,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
gotoProviderButton.Margin = new BorderDouble(right: 5);
gotoProviderButton.Click += (s, e) =>
{
UiThread.RunOnIdle(() => listView.LoadContainer(container));
UiThread.RunOnIdle(() => listView.SetActiveContainer(container));
};
this.AddChild(gotoProviderButton);

View file

@ -127,10 +127,16 @@ namespace MatterHackers.MatterControl
if (thumbnail != null)
{
// Cache big render
string cachePath = ApplicationController.Instance.ThumbnailCachePath(item);
AggContext.ImageIO.SaveImageData(cachePath, thumbnail);
if(ApplicationController.Instance.Library.ActiveContainer is ILibraryWritableContainer writableContainer)
// Cache at requested size
cachePath = ApplicationController.Instance.ThumbnailCachePath(item, width, height);
thumbnail = LibraryProviderHelpers.ResizeImage(thumbnail, width, height);
AggContext.ImageIO.SaveImageData(cachePath, thumbnail);
if (ApplicationController.Instance.Library.ActiveContainer is ILibraryWritableContainer writableContainer)
{
writableContainer.SetThumbnail(item, thumbnail.Width, thumbnail.Height, thumbnail);
}

View file

@ -68,6 +68,9 @@ namespace MatterHackers.MatterControl.Library
protected void OnContentChanged()
{
// Reload the container when new contents are available
this.Load();
this.ContentChanged?.Invoke(this, null);
}

View file

@ -160,12 +160,6 @@ namespace MatterHackers.MatterControl.CustomWidgets
var itemsContentView = contentView as IListContentView;
itemsContentView.ClearItems();
// Wait for the container to load
await Task.Run(() =>
{
sourceContainer.Load();
});
int width = itemsContentView.ThumbWidth;
int height = itemsContentView.ThumbHeight;
@ -221,7 +215,6 @@ namespace MatterHackers.MatterControl.CustomWidgets
if (firstItem != null)
{
firstItem.ViewWidget.LoadItemThumbnail().ConfigureAwait(false);
firstItem.ViewWidget.Invalidate();
}
}
@ -264,23 +257,57 @@ namespace MatterHackers.MatterControl.CustomWidgets
}
}
internal ImageBuffer LoadCachedImage(ListViewItem listViewItem)
internal ImageBuffer LoadCachedImage(ListViewItem listViewItem, int width, int height)
{
string cachePath = ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model);
bool isCached = !string.IsNullOrEmpty(cachePath) && File.Exists(cachePath);
if (isCached)
ImageBuffer cachedItem = LoadImage(ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model, width, height));
if (cachedItem != null)
{
ImageBuffer thumbnail = new ImageBuffer();
AggContext.ImageIO.LoadImageData(cachePath, thumbnail);
thumbnail.SetRecieveBlender(new BlenderPreMultBGRA());
return cachedItem;
}
return thumbnail;
// Check for big render, resize, cache and return
var bigRender = LoadImage(ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model));
if (bigRender != null)
{
try
{
var thumbnail = LibraryProviderHelpers.ResizeImage(bigRender, width, height);
// Cache at requested size
AggContext.ImageIO.SaveImageData(
ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model, width, height),
thumbnail);
return thumbnail;
}
catch { } // suppress and return null on errors
}
return null;
}
private ImageBuffer LoadImage(string filePath)
{
ImageBuffer thumbnail = null;
try
{
if (File.Exists(filePath))
{
var temp = new ImageBuffer();
AggContext.ImageIO.LoadImageData(filePath, temp);
temp.SetRecieveBlender(new BlenderPreMultBGRA());
thumbnail = temp;
}
return thumbnail;
}
catch { } // Suppress exceptions, return null on any errors
return thumbnail;
}
// TODO: ResizeCanvas is also colorizing thumbnails as a proof of concept
public ImageBuffer ResizeCanvas(ImageBuffer originalImage, int width, int height)
{
@ -308,7 +335,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
private void listViewItem_DoubleClick(object sender, MouseEventArgs e)
{
UiThread.RunOnIdle((Action)(async () =>
UiThread.RunOnIdle(async () =>
{
var listViewItem = sender as ListViewItem;
var itemModel = listViewItem.Model;
@ -320,10 +347,15 @@ namespace MatterHackers.MatterControl.CustomWidgets
if (containerLink != null)
{
var container = await containerLink.GetContainer(null);
await Task.Run(() =>
{
container.Load();
});
if (container != null)
{
container.Parent = ActiveContainer;
LoadContainer(container);
SetActiveContainer(container);
}
}
}
@ -366,12 +398,12 @@ namespace MatterHackers.MatterControl.CustomWidgets
}
}
}
}));
});
}
public void LoadContainer(ILibraryContainer temp)
public void SetActiveContainer(ILibraryContainer container)
{
this.LibraryContext.ActiveContainer = temp;
this.LibraryContext.ActiveContainer = container;
}
public ObservableCollection<ListViewItem> SelectedItems { get; } = new ObservableCollection<ListViewItem>();

View file

@ -93,7 +93,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
{
var listView = listViewItem.ListView;
var thumbnail = listView.LoadCachedImage(listViewItem);
var thumbnail = listView.LoadCachedImage(listViewItem, thumbWidth, thumbHeight);
if (thumbnail != null)
{
SetItemThumbnail(thumbnail);

View file

@ -81,6 +81,8 @@
<Compile Include="ActionBar\PrinterSelector.cs" />
<Compile Include="ActionBar\ResetButton.cs" />
<Compile Include="ActionBar\TemperatureWidgetBed.cs" />
<Compile Include="ApplicationView\OemProfileDictionary.cs" />
<Compile Include="ApplicationView\WindowsPlatformsFeatures.cs" />
<Compile Include="PartPreviewWindow\View3D\PrinterBar\PrintPopupMenu.cs" />
<Compile Include="PartPreviewWindow\View3D\PrinterBar\SliceButton.cs" />
<Compile Include="PartPreviewWindow\View3D\PrinterBar\PrinterConnectButton.cs" />
@ -149,6 +151,7 @@
<Compile Include="PrinterControls\MacroDetailPage.cs" />
<Compile Include="PrinterControls\MacroListPage.cs" />
<Compile Include="PrinterControls\PrinterConnections\PrinterSetup.cs" />
<Compile Include="RootSystemWindow.cs" />
<Compile Include="SetupWizard\DialogWindow.cs" />
<Compile Include="Utilities\InspectForm.cs" Condition="'$(Configuration)' == 'Debug'">
<SubType>Form</SubType>
@ -374,7 +377,6 @@
<Compile Include="DataStorage\Datastore.cs" />
<Compile Include="DataStorage\SQLiteUnix.cs" />
<Compile Include="DataStorage\SQLiteAsync.cs" />
<Compile Include="ApplicationView\MainApplicationWidget.cs" />
<Compile Include="Utilities\ManifestFileHandler.cs">
<SubType>Code</SubType>
</Compile>

View file

@ -33,631 +33,33 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.ImageProcessing;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PartPreviewWindow;
using MatterHackers.MatterControl.PluginSystem;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.PrinterControls.PrinterConnections;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.MatterControl.SettingsManagement;
using MatterHackers.MatterControl.SlicerConfiguration;
using MatterHackers.PolygonMesh.Processors;
using MatterHackers.RenderOpenGl.OpenGl;
using MatterHackers.VectorMath;
using Mindscape.Raygun4Net;
namespace MatterHackers.MatterControl
{
public class MatterControlApplication : SystemWindow
public static class MatterControlApplication
{
#if DEBUG
//public static string MCWSBaseUri { get; } = "http://192.168.2.129:9206";
public static string MCWSBaseUri { get; } = "https://mattercontrol-test.appspot.com";
#else
public static string MCWSBaseUri { get; } = "https://mattercontrol.appspot.com";
#endif
public static bool CameraInUseByExternalProcess { get; set; } = false;
public bool RestartOnClose = false;
private static MatterControlApplication instance;
private string[] commandLineArgs = null;
private bool DoCGCollectEveryDraw = false;
private int drawCount = 0;
private AverageMillisecondTimer millisecondTimer = new AverageMillisecondTimer();
private bool ShowMemoryUsed = false;
public void ConfigureWifi()
{
}
private Stopwatch totalDrawTime = new Stopwatch();
public static bool IsLoading { get; private set; } = true;
public static void RequestPowerShutDown()
{
// does nothing on windows
}
static MatterControlApplication()
{
if (AggContext.OperatingSystem == OSType.Mac && AggContext.StaticData == null)
{
// Set working directory - this duplicates functionality in Main but is necessary on OSX as Main fires much later (after the constructor in this case)
// resulting in invalid paths due to path tests running before the working directory has been overridden. Setting the value before initializing StaticData
// works around this architectural difference.
Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));
}
// Because fields on this class call localization methods and because those methods depend on the StaticData provider and because the field
// initializers run before the class constructor, we need to init the platform specific provider in the static constructor (or write a custom initializer method)
//
// Initialize a standard file system backed StaticData provider
if (AggContext.StaticData == null) // it may already be initialized by tests
{
AggContext.StaticData = new MatterHackers.Agg.FileSystemStaticData();
}
#if DEBUG
WinformsSystemWindow.InspectorCreator = (systemWindow) =>
{
if (systemWindow == Instance)
{
// If systemWindow is MatterControlApplication, include Scene
var partContext = ApplicationController.Instance.DragDropData;
return new InspectForm(systemWindow, partContext.SceneContext.Scene, partContext.View3DWidget);
}
else
{
// Otherwise, exclude Scene
return new InspectForm(systemWindow);
}
};
#endif
}
private MatterControlApplication(double width, double height)
: base(width, height)
{
ApplicationSettings.Instance.set("HardwareHasCamera", "false");
Name = "MatterControl";
// set this at startup so that we can tell next time if it got set to true in close
UserSettings.Instance.Fields.StartCount = UserSettings.Instance.Fields.StartCount + 1;
this.commandLineArgs = Environment.GetCommandLineArgs();
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
for (int currentCommandIndex = 0; currentCommandIndex < commandLineArgs.Length; currentCommandIndex++)
{
string command = commandLineArgs[currentCommandIndex];
string commandUpper = command.ToUpper();
switch (commandUpper)
{
case "FORCE_SOFTWARE_RENDERING":
GL.HardwareAvailable = false;
break;
case "CLEAR_CACHE":
AboutWidget.DeleteCacheData(0);
break;
case "SHOW_MEMORY":
ShowMemoryUsed = true;
break;
case "DO_GC_COLLECT_EVERY_DRAW":
ShowMemoryUsed = true;
DoCGCollectEveryDraw = true;
break;
}
if (MeshFileIo.ValidFileExtensions().Contains(Path.GetExtension(command).ToUpper()))
{
// If we are the only instance running then do nothing.
// Else send these to the running instance so it can load them.
}
}
#if IS_WINDOWS_FORMS
if (!Clipboard.IsInitialized)
{
Clipboard.SetSystemClipboard(new WindowsFormsClipboard());
}
#endif
GuiWidget.DefaultEnforceIntegerBounds = true;
if (UserSettings.Instance.IsTouchScreen)
{
GuiWidget.DeviceScale = 1.3;
SystemWindow.ShareSingleOsWindow = true;
}
string textSizeMode = UserSettings.Instance.get(UserSettingsKey.ApplicationTextSize);
if (!string.IsNullOrEmpty(textSizeMode))
{
double textSize = 1.0;
if(double.TryParse(textSizeMode, out textSize))
{
GuiWidget.DeviceScale = textSize;
}
}
//GuiWidget.DeviceScale = 2;
using (new PerformanceTimer("Startup", "MainView"))
{
this.AddChild(ApplicationController.Instance.MainView);
}
this.MinimumSize = minSize;
this.Padding = new BorderDouble(0); //To be re-enabled once native borders are turned off
#if false // this is to test freeing gcodefile memory
Button test = new Button("test");
test.Click += (sender, e) =>
{
//MatterHackers.GCodeVisualizer.GCodeFile gcode = new GCodeVisualizer.GCodeFile();
//gcode.Load(@"C:\Users\lbrubaker\Downloads\drive assy.gcode");
SystemWindow window = new SystemWindow(100, 100);
window.ShowAsSystemWindow();
};
allControls.AddChild(test);
#endif
this.AnchorAll();
if (GL.HardwareAvailable)
{
UseOpenGL = true;
}
string version = "2.0";
Title = "MatterHackers: MatterControl {0}".FormatWith(version);
if (OemSettings.Instance.WindowTitleExtra != null && OemSettings.Instance.WindowTitleExtra.Trim().Length > 0)
{
Title = Title + " - {1}".FormatWith(version, OemSettings.Instance.WindowTitleExtra);
}
Title = IntPtr.Size == 4 ? Title + " - 32Bit" : Title = Title + " - 64Bit";
UiThread.RunOnIdle(CheckOnPrinter);
string desktopPosition = ApplicationSettings.Instance.get(ApplicationSettingsKey.DesktopPosition);
if (!string.IsNullOrEmpty(desktopPosition))
{
string[] sizes = desktopPosition.Split(',');
//If the desktop position is less than -10,-10, override
int xpos = Math.Max(int.Parse(sizes[0]), -10);
int ypos = Math.Max(int.Parse(sizes[1]), -10);
this.InitialDesktopPosition = new Point2D(xpos, ypos);
}
else
{
this.InitialDesktopPosition = new Point2D(-1, -1);
}
this.Maximized = ApplicationSettings.Instance.get(ApplicationSettingsKey.MainWindowMaximized) == "true";
}
public void TakePhoto(string imageFileName)
{
ImageBuffer noCameraImage = new ImageBuffer(640, 480);
Graphics2D graphics = noCameraImage.NewGraphics2D();
graphics.Clear(Color.White);
graphics.DrawString("No Camera Detected", 320, 240, pointSize: 24, justification: Agg.Font.Justification.Center);
graphics.DrawString(DateTime.Now.ToString(), 320, 200, pointSize: 12, justification: Agg.Font.Justification.Center);
AggContext.ImageIO.SaveImageData(imageFileName, noCameraImage);
PictureTaken?.Invoke(null, null);
}
private bool dropWasOnChild = true;
private EventHandler unregisterEvent;
public static MatterControlApplication Instance
{
get
{
if (instance == null)
{
instance = CreateInstance();
instance.ShowAsSystemWindow();
}
return instance;
}
}
public event EventHandler PictureTaken;
private static Vector2 minSize { get; set; } = new Vector2(600, 600);
public static MatterControlApplication CreateInstance(int overrideWidth = -1, int overrideHeight = -1)
{
int width = 0;
int height = 0;
if (UserSettings.Instance.IsTouchScreen)
{
minSize = new Vector2(800, 480);
}
// check if the app has a size already set
string windowSize = ApplicationSettings.Instance.get(ApplicationSettingsKey.WindowSize);
if (windowSize != null && windowSize != "")
{
// try and open our window matching the last size that we had for it.
string[] sizes = windowSize.Split(',');
width = Math.Max(int.Parse(sizes[0]), (int)minSize.X + 1);
height = Math.Max(int.Parse(sizes[1]), (int)minSize.Y + 1);
}
else // try to set it to a big size or the min size
{
Point2D desktopSize = AggContext.DesktopSize;
if (overrideWidth != -1)
{
width = overrideWidth;
}
else // try to set it to a good size
{
if (width < desktopSize.x)
{
width = 1280;
}
}
if (overrideHeight != -1)
{
// Height should be constrained to actual
height = Math.Min(overrideHeight, desktopSize.y);
}
else
{
if (height < desktopSize.y)
{
height = 720;
}
}
}
using (new PerformanceTimer("Startup", "Total"))
{
instance = new MatterControlApplication(width, height);
}
return instance;
}
public void LaunchBrowser(string targetUri)
{
UiThread.RunOnIdle(() =>
{
System.Diagnostics.Process.Start(targetUri);
});
}
public override void OnClosed(ClosedEventArgs e)
{
UserSettings.Instance.Fields.StartCountDurringExit = UserSettings.Instance.Fields.StartCount;
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
{
ApplicationController.Instance.ActivePrinter.Connection.Disable();
}
//Close connection to the local datastore
ApplicationController.Instance.ActivePrinter.Connection.HaltConnectionThread();
ApplicationController.Instance.OnApplicationClosed();
Datastore.Instance.Exit();
if (RestartOnClose)
{
string appPathAndFile = System.Reflection.Assembly.GetExecutingAssembly().Location;
string pathToAppFolder = Path.GetDirectoryName(appPathAndFile);
ProcessStartInfo runAppLauncherStartInfo = new ProcessStartInfo();
runAppLauncherStartInfo.Arguments = "\"{0}\" \"{1}\"".FormatWith(appPathAndFile, 1000);
runAppLauncherStartInfo.FileName = Path.Combine(pathToAppFolder, "Launcher.exe");
runAppLauncherStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
runAppLauncherStartInfo.CreateNoWindow = true;
Process.Start(runAppLauncherStartInfo);
}
base.OnClosed(e);
}
public override void OnClosing(ClosingEventArgs eventArgs)
{
if (this.HasBeenClosed)
{
return;
}
// save the last size of the window so we can restore it next time.
ApplicationSettings.Instance.set(ApplicationSettingsKey.MainWindowMaximized, this.Maximized.ToString().ToLower());
if (!this.Maximized)
{
ApplicationSettings.Instance.set(ApplicationSettingsKey.WindowSize, string.Format("{0},{1}", Width, Height));
ApplicationSettings.Instance.set(ApplicationSettingsKey.DesktopPosition, string.Format("{0},{1}", DesktopPosition.x, DesktopPosition.y));
}
//Save a snapshot of the prints in queue
QueueData.Instance.SaveDefaultQueue();
// If we are waiting for a response and get another request, just cancel the close until we get a response.
if(exitDialogOpen)
{
eventArgs.Cancel = true;
}
string caption = null;
string message = null;
if (!ApplicationExiting
&& !exitDialogOpen
&& ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting)
{
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
{
caption = "Abort Print".Localize();
message = "Are you sure you want to abort the current print and close MatterControl?".Localize();
}
else
{
caption = "Exit while printing".Localize();
message = "Are you sure you want exit while a print is running from SD Card?\n\nNote: If you exit, it is recommended you wait until the print is completed before running MatterControl again.".Localize();
}
}
else if (PartsSheet.IsSaving())
{
caption = "Confirm Exit".Localize();
message = "You are currently saving a parts sheet, are you sure you want to exit?".Localize();
}
if (caption != null)
{
// Record that we are waiting for a response to the request to close
exitDialogOpen = true;
// We need to show an interactive dialog to determine if the original Close request should be honored, thus cancel the current Close request
eventArgs.Cancel = true;
UiThread.RunOnIdle(() =>
{
StyledMessageBox.ShowMessageBox(
(exitConfirmed) =>
{
// Record that the exitDialog has closed
exitDialogOpen = false;
// Continue with the original shutdown request if exit confirmed by user
if (exitConfirmed)
{
this.ApplicationExiting = true;
ApplicationController.Instance.Shutdown();
// Always call PrinterConnection.Disable on exit unless PrintingFromSd
PrinterConnection printerConnection = ApplicationController.Instance.ActivePrinter.Connection;
switch (printerConnection.CommunicationState)
{
case CommunicationStates.PrintingFromSd:
case CommunicationStates.Paused when printerConnection.PrePauseCommunicationState == CommunicationStates.PrintingFromSd:
break;
default:
printerConnection.Disable();
break;
}
MatterControlApplication.instance.CloseOnIdle();
this.RestartOnClose = false;
}
},
message,
caption,
StyledMessageBox.MessageType.YES_NO);
});
}
else
{
this.ApplicationExiting = true;
}
}
public bool ApplicationExiting { get; private set; } = false;
private bool exitDialogOpen = false;
public override void OnDraw(Graphics2D graphics2D)
{
totalDrawTime.Restart();
GuiWidget.DrawCount = 0;
using (new PerformanceTimer("Draw Timer", "MC Draw"))
{
base.OnDraw(graphics2D);
}
totalDrawTime.Stop();
millisecondTimer.Update((int)totalDrawTime.ElapsedMilliseconds);
if (ShowMemoryUsed)
{
long memory = GC.GetTotalMemory(false);
this.Title = "Allocated = {0:n0} : {1:000}ms, d{2} Size = {3}x{4}, onIdle = {5:00}:{6:00}, widgetsDrawn = {7}".FormatWith(memory, millisecondTimer.GetAverage(), drawCount++, this.Width, this.Height, UiThread.CountExpired, UiThread.Count, GuiWidget.DrawCount);
if (DoCGCollectEveryDraw)
{
GC.Collect();
}
}
//msGraph.AddData("ms", totalDrawTime.ElapsedMilliseconds);
//msGraph.Draw(MatterHackers.Agg.Transform.Affine.NewIdentity(), graphics2D);
}
public override void OnLoad(EventArgs args)
{
// Moved from OnParentChanged
if (File.Exists("RunUnitTests.txt"))
{
//DiagnosticWidget diagnosticView = new DiagnosticWidget(this);
}
// now that we are all set up lets load our plugins and allow them their chance to set things up
FindAndInstantiatePlugins();
if (ApplicationController.Instance.PluginsLoaded != null)
{
ApplicationController.Instance.PluginsLoaded.CallEvents(null, null);
}
foreach (string arg in commandLineArgs)
{
string argExtension = Path.GetExtension(arg).ToUpper();
if (argExtension.Length > 1
&& MeshFileIo.ValidFileExtensions().Contains(argExtension))
{
QueueData.Instance.AddItem(new PrintItemWrapper(new PrintItem(Path.GetFileName(arg), Path.GetFullPath(arg))));
}
}
ApplicationController.Instance.OnLoadActions();
//HtmlWindowTest();
IsLoading = false;
base.OnLoad(args);
}
public override void OnMouseMove(MouseEventArgs mouseEvent)
{
// run this first to make sure a child has the chance to take the drag drop event
base.OnMouseMove(mouseEvent);
if (!mouseEvent.AcceptDrop && mouseEvent.DragFiles != null)
{
// no child has accepted the drop
foreach (string file in mouseEvent.DragFiles)
{
string extension = Path.GetExtension(file).ToUpper();
if ((extension != "" && MeshFileIo.ValidFileExtensions().Contains(extension))
|| extension == ".GCODE"
|| extension == ".ZIP")
{
//mouseEvent.AcceptDrop = true;
}
}
dropWasOnChild = false;
}
else
{
dropWasOnChild = true;
}
if (GuiWidget.DebugBoundsUnderMouse)
{
Invalidate();
}
}
public void OpenCameraPreview()
{
//Camera launcher placeholder (KP)
if (ApplicationSettings.Instance.get(ApplicationSettingsKey.HardwareHasCamera) == "true")
{
//Do something
}
else
{
//Do something else (like show warning message)
}
}
public void PlaySound(string fileName)
{
if (AggContext.OperatingSystem == OSType.Windows)
{
using (var mediaStream = AggContext.StaticData.OpenSteam(Path.Combine("Sounds", fileName)))
{
(new System.Media.SoundPlayer(mediaStream)).Play();
}
}
}
private void CheckOnPrinter()
{
try
{
ApplicationController.Instance.ActivePrinter.Connection.OnIdle();
}
catch (Exception e)
{
Debug.Print(e.Message);
GuiWidget.BreakInDebugger();
#if DEBUG
throw e;
#endif
}
UiThread.RunOnIdle(CheckOnPrinter);
}
private void FindAndInstantiatePlugins()
{
#if false
string pluginDirectory = Path.Combine("..", "..", "..", "MatterControlPlugins", "bin");
#if DEBUG
pluginDirectory = Path.Combine(pluginDirectory, "Debug");
#else
pluginDirectory = Path.Combine(pluginDirectory, "Release");
#endif
if (!Directory.Exists(pluginDirectory))
{
string dataPath = ApplicationDataStorage.Instance.ApplicationUserDataPath;
pluginDirectory = Path.Combine(dataPath, "Plugins");
}
// TODO: this should look in a plugin folder rather than just the application directory (we probably want it in the user folder).
PluginFinder<MatterControlPlugin> pluginFinder = new PluginFinder<MatterControlPlugin>(pluginDirectory);
#endif
string oemName = ApplicationSettings.Instance.GetOEMName();
foreach (MatterControlPlugin plugin in PluginFinder.CreateInstancesOf<MatterControlPlugin>())
{
string pluginInfo = plugin.GetPluginInfoJSon();
Dictionary<string, string> nameValuePairs = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(pluginInfo);
if (nameValuePairs != null && nameValuePairs.ContainsKey("OEM"))
{
if (nameValuePairs["OEM"] == oemName)
{
plugin.Initialize(this);
}
}
else
{
plugin.Initialize(this);
}
}
}
private static void AssertDebugNotDefined()
{
#if DEBUG
@ -679,10 +81,5 @@ namespace MatterHackers.MatterControl
MatterHackers.MeshVisualizer.MeshViewerWidget.AssertDebugNotDefined();
MatterHackers.RenderOpenGl.GLMeshTrianglePlugin.AssertDebugNotDefined();
}
public bool IsNetworkConnected()
{
return true;
}
}
}

View file

@ -81,11 +81,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab
{
if (item.url != null)
{
MatterControlApplication.Instance.LaunchBrowser("http://www.matterhackers.com/" + item.url);
ApplicationController.Instance.LaunchBrowser("http://www.matterhackers.com/" + item.url);
}
else if (item.link != null)
{
MatterControlApplication.Instance.LaunchBrowser(item.link);
ApplicationController.Instance.LaunchBrowser(item.link);
}
base.OnClick(mouseEvent);

View file

@ -120,7 +120,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab
imageWidget.Cursor = Cursors.Hand;
imageWidget.Click += (s, e) =>
{
MatterControlApplication.Instance.LaunchBrowser(content.link);
ApplicationController.Instance.LaunchBrowser(content.link);
};
}

View file

@ -534,8 +534,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
// When GCode changes, switch to the 3D layer view
printer.ViewState.ViewMode = PartViewMode.Layers3D;
// HACK: directly fire method which previously ran on SlicingDone event on PrintItemWrapper
UiThread.RunOnIdle(() => printerTabPage.gcode3DWidget.CreateAndAddChildren(printer));
if (printerTabPage.gcode3DWidget != null)
{
// HACK: directly fire method which previously ran on SlicingDone event on PrintItemWrapper
UiThread.RunOnIdle(() => printerTabPage.gcode3DWidget.CreateAndAddChildren(printer));
}
}
}

View file

@ -217,7 +217,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
break;
case "ding":
MatterControlApplication.Instance.PlaySound("timer-done.wav");
AppContext.Platform.PlaySound("timer-done.wav");
break;
case "show_message":

View file

@ -42,7 +42,7 @@ namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections
public static DialogPage GetBestStartPage(StartPageOptions options = StartPageOptions.Default)
{
// Do the printer setup logic
bool WifiDetected = MatterControlApplication.Instance.IsNetworkConnected();
bool WifiDetected = AppContext.Platform.IsNetworkConnected();
if (!WifiDetected
&& options != StartPageOptions.SkipWifiSetup)
{

View file

@ -1,8 +1,13 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.Font;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.SettingsManagement;
using Mindscape.Raygun4Net;
@ -11,17 +16,20 @@ namespace MatterHackers.MatterControl
{
static class Program
{
private const int RaygunMaxNotifications = 15;
private const int RaygunMaxNotifications = 15;
private static int raygunNotificationCount = 0;
private static int raygunNotificationCount = 0;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static RaygunClient _raygunClient = GetCorrectClient();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
public static void Main()
{
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
AggContext.Init(embeddedResourceName: "config.json");
@ -29,7 +37,6 @@ namespace MatterHackers.MatterControl
// Make sure we have the right working directory as we assume everything relative to the executable.
Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));
Datastore.Instance.Initialize();
#if !DEBUG
// Conditionally spin up error reporting if not on the Stable channel
@ -41,7 +48,11 @@ namespace MatterHackers.MatterControl
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
MatterControlApplication app = MatterControlApplication.Instance;
// Get startup bounds from MatterControl and construct system window
//var systemWindow = new DesktopMainWindow(400, 200)
var (width, height) = RootSystemWindow.GetStartupBounds();
Application.LoadRootWindow(width, height).ShowAsSystemWindow();
}
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
@ -64,27 +75,25 @@ namespace MatterHackers.MatterControl
#endif
}
private static RaygunClient _raygunClient = GetCorrectClient();
private static RaygunClient GetCorrectClient()
{
if (AggContext.OperatingSystem == OSType.Mac)
{
return new RaygunClient("qmMBpKy3OSTJj83+tkO7BQ=="); // this is the Mac key
}
else
{
return new RaygunClient("hQIlyUUZRGPyXVXbI6l1dA=="); // this is the PC key
}
}
private static RaygunClient GetCorrectClient()
{
if (AggContext.OperatingSystem == OSType.Mac)
{
return new RaygunClient("qmMBpKy3OSTJj83+tkO7BQ=="); // this is the Mac key
}
else
{
return new RaygunClient("hQIlyUUZRGPyXVXbI6l1dA=="); // this is the PC key
}
}
// ** Standard Winforms Main ** //
//[STAThread]
//static void Main()
//{
// Application.EnableVisualStyles();
// Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1());
//}
}
// ** Standard Winforms Main ** //
//[STAThread]
//static void Main()
//{
// Application.EnableVisualStyles();
// Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1());
//}
}
}

376
RootSystemWindow.cs Normal file
View file

@ -0,0 +1,376 @@
/*
Copyright (c) 2016, Lars Brubaker, Kevin Pope
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
*/
using System;
using System.Diagnostics;
using System.IO;
using MatterHackers.Agg;
using MatterHackers.Agg.Platform;
using MatterHackers.Agg.UI;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrinterCommunication;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.MatterControl.SettingsManagement;
using MatterHackers.RenderOpenGl.OpenGl;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl
{
public class RootSystemWindow : SystemWindow
{
private static Vector2 minSize { get; set; } = new Vector2(600, 600);
private Stopwatch totalDrawTime = new Stopwatch();
private bool dropWasOnChild = true;
private AverageMillisecondTimer millisecondTimer = new AverageMillisecondTimer();
internal static bool ShowMemoryUsed = false;
private int drawCount = 0;
private bool exitDialogOpen = false;
public RootSystemWindow(double width, double height)
: base(width, height)
{
this.Name = "MatterControl";
this.Padding = new BorderDouble(0); //To be re-enabled once native borders are turned off
this.AnchorAll();
GuiWidget.DefaultEnforceIntegerBounds = true;
// TODO: Needs review - doesn't seem like we want to scale on Touchscreen, rather we want device specific, configuration based scaling. Suggest remove
if (UserSettings.Instance.IsTouchScreen)
{
GuiWidget.DeviceScale = 1.3;
SystemWindow.ShareSingleOsWindow = true;
}
string textSizeMode = UserSettings.Instance.get(UserSettingsKey.ApplicationTextSize);
if (!string.IsNullOrEmpty(textSizeMode))
{
double textSize = 1.0;
if (double.TryParse(textSizeMode, out textSize))
{
GuiWidget.DeviceScale = textSize;
}
}
if (GL.HardwareAvailable)
{
UseOpenGL = true;
}
this.SetStartupTraits();
}
public void SetStartupTraits()
{
string version = "2.0";
this.MinimumSize = minSize;
this.Title = "MatterHackers: MatterControl {0}".FormatWith(version);
if (OemSettings.Instance.WindowTitleExtra != null && OemSettings.Instance.WindowTitleExtra.Trim().Length > 0)
{
this.Title = this.Title + " - {1}".FormatWith(version, OemSettings.Instance.WindowTitleExtra);
}
this.Title = IntPtr.Size == 4 ? this.Title + " - 32Bit" : this.Title = this.Title + " - 64Bit";
string desktopPosition = ApplicationSettings.Instance.get(ApplicationSettingsKey.DesktopPosition);
if (!string.IsNullOrEmpty(desktopPosition))
{
string[] sizes = desktopPosition.Split(',');
//If the desktop position is less than -10,-10, override
int xpos = Math.Max(int.Parse(sizes[0]), -10);
int ypos = Math.Max(int.Parse(sizes[1]), -10);
this.DesktopPosition = new Point2D(xpos, ypos);
}
else
{
this.DesktopPosition = new Point2D(-1, -1);
}
this.Maximized = ApplicationSettings.Instance.get(ApplicationSettingsKey.MainWindowMaximized) == "true";
#if IS_WINDOWS_FORMS
if (!Clipboard.IsInitialized)
{
Clipboard.SetSystemClipboard(new WindowsFormsClipboard());
}
#endif
#if DEBUG && !__ANDROID__
WinformsSystemWindow.InspectorCreator = (inspectingWindow) =>
{
if (inspectingWindow == this)
{
// If this is MatterControlApplication, include Scene
var partContext = ApplicationController.Instance.DragDropData;
return new InspectForm(inspectingWindow, partContext.SceneContext.Scene, partContext.View3DWidget);
}
else
{
// Otherwise, exclude Scene
return new InspectForm(inspectingWindow);
}
};
#endif
}
public static (int width, int height) GetStartupBounds(int overrideWidth = -1, int overrideHeight = -1)
{
int width = 0;
int height = 0;
if (UserSettings.Instance.IsTouchScreen)
{
minSize = new Vector2(800, 480);
}
// check if the app has a size already set
string windowSize = ApplicationSettings.Instance.get(ApplicationSettingsKey.WindowSize);
if (windowSize != null && windowSize != "")
{
// try and open our window matching the last size that we had for it.
string[] sizes = windowSize.Split(',');
width = Math.Max(int.Parse(sizes[0]), (int)minSize.X + 1);
height = Math.Max(int.Parse(sizes[1]), (int)minSize.Y + 1);
}
else // try to set it to a big size or the min size
{
Point2D desktopSize = AggContext.DesktopSize;
if (overrideWidth != -1)
{
width = overrideWidth;
}
else // try to set it to a good size
{
if (width < desktopSize.x)
{
width = 1280;
}
}
if (overrideHeight != -1)
{
// Height should be constrained to actual
height = Math.Min(overrideHeight, desktopSize.y);
}
else
{
if (height < desktopSize.y)
{
height = 720;
}
}
}
return (width, height);
}
public override void OnDraw(Graphics2D graphics2D)
{
totalDrawTime.Restart();
GuiWidget.DrawCount = 0;
using (new PerformanceTimer("Draw Timer", "MC Draw"))
{
base.OnDraw(graphics2D);
}
totalDrawTime.Stop();
millisecondTimer.Update((int)totalDrawTime.ElapsedMilliseconds);
if (ShowMemoryUsed)
{
long memory = GC.GetTotalMemory(false);
this.Title = "Allocated = {0:n0} : {1:000}ms, d{2} Size = {3}x{4}, onIdle = {5:00}:{6:00}, widgetsDrawn = {7}".FormatWith(memory, millisecondTimer.GetAverage(), drawCount++, this.Width, this.Height, UiThread.CountExpired, UiThread.Count, GuiWidget.DrawCount);
}
//msGraph.AddData("ms", totalDrawTime.ElapsedMilliseconds);
//msGraph.Draw(MatterHackers.Agg.Transform.Affine.NewIdentity(), graphics2D);
}
public override void OnClosing(ClosingEventArgs eventArgs)
{
if (this.HasBeenClosed)
{
return;
}
// save the last size of the window so we can restore it next time.
ApplicationSettings.Instance.set(ApplicationSettingsKey.MainWindowMaximized, this.Maximized.ToString().ToLower());
if (!this.Maximized)
{
ApplicationSettings.Instance.set(ApplicationSettingsKey.WindowSize, string.Format("{0},{1}", Width, Height));
ApplicationSettings.Instance.set(ApplicationSettingsKey.DesktopPosition, string.Format("{0},{1}", DesktopPosition.x, DesktopPosition.y));
}
//Save a snapshot of the prints in queue
QueueData.Instance.SaveDefaultQueue();
// If we are waiting for a response and get another request, just cancel the close until we get a response.
if (exitDialogOpen)
{
eventArgs.Cancel = true;
}
string caption = null;
string message = null;
if (!ApplicationController.Instance.ApplicationExiting
&& !exitDialogOpen
&& ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting)
{
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
{
caption = "Abort Print".Localize();
message = "Are you sure you want to abort the current print and close MatterControl?".Localize();
}
else
{
caption = "Exit while printing".Localize();
message = "Are you sure you want exit while a print is running from SD Card?\n\nNote: If you exit, it is recommended you wait until the print is completed before running MatterControl again.".Localize();
}
}
#if !__ANDROID__
else if (PartsSheet.IsSaving())
{
caption = "Confirm Exit".Localize();
message = "You are currently saving a parts sheet, are you sure you want to exit?".Localize();
}
#endif
if (caption != null)
{
// Record that we are waiting for a response to the request to close
exitDialogOpen = true;
// We need to show an interactive dialog to determine if the original Close request should be honored, thus cancel the current Close request
eventArgs.Cancel = true;
UiThread.RunOnIdle(() =>
{
StyledMessageBox.ShowMessageBox(
(exitConfirmed) =>
{
// Record that the exitDialog has closed
exitDialogOpen = false;
// Continue with the original shutdown request if exit confirmed by user
if (exitConfirmed)
{
ApplicationController.Instance.ApplicationExiting = true;
ApplicationController.Instance.Shutdown();
// Always call PrinterConnection.Disable on exit unless PrintingFromSd
PrinterConnection printerConnection = ApplicationController.Instance.ActivePrinter.Connection;
switch (printerConnection.CommunicationState)
{
case CommunicationStates.PrintingFromSd:
case CommunicationStates.Paused when printerConnection.PrePauseCommunicationState == CommunicationStates.PrintingFromSd:
break;
default:
printerConnection.Disable();
break;
}
this.CloseOnIdle();
}
},
message,
caption,
StyledMessageBox.MessageType.YES_NO);
});
}
else
{
ApplicationController.Instance.ApplicationExiting = true;
}
}
public override void OnClosed(ClosedEventArgs e)
{
UserSettings.Instance.Fields.StartCountDurringExit = UserSettings.Instance.Fields.StartCount;
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
{
ApplicationController.Instance.ActivePrinter.Connection.Disable();
}
//Close connection to the local datastore
ApplicationController.Instance.ActivePrinter.Connection.HaltConnectionThread();
ApplicationController.Instance.OnApplicationClosed();
Datastore.Instance.Exit();
base.OnClosed(e);
}
public override void OnMouseMove(MouseEventArgs mouseEvent)
{
// run this first to make sure a child has the chance to take the drag drop event
base.OnMouseMove(mouseEvent);
if (!mouseEvent.AcceptDrop && mouseEvent.DragFiles != null)
{
// no child has accepted the drop
foreach (string file in mouseEvent.DragFiles)
{
string extension = Path.GetExtension(file).ToUpper();
if ((extension != "" && MeshFileIo.ValidFileExtensions().Contains(extension))
|| extension == ".GCODE"
|| extension == ".ZIP")
{
//mouseEvent.AcceptDrop = true;
}
}
dropWasOnChild = false;
}
else
{
dropWasOnChild = true;
}
if (GuiWidget.DebugBoundsUnderMouse)
{
Invalidate();
}
}
}
}

View file

@ -206,7 +206,7 @@ namespace MatterHackers.MatterControl.SettingsManagement
await Task.Delay(20000);
await ProfileManager.LoadOemProfileAsync(publicDevice, oem, model);
if (MatterControlApplication.Instance.ApplicationExiting)
if (ApplicationController.Instance.ApplicationExiting)
{
return;
}

View file

@ -46,7 +46,7 @@ namespace MatterHackers.MatterControl
configureButton.Margin = new BorderDouble(0, 0, 10, 0);
configureButton.Click += (s, e) =>
{
MatterControlApplication.Instance.ConfigureWifi();
MatterControl.AppContext.Platform.ConfigureWifi();
UiThread.RunOnIdle(WizardWindow.Close, 1);
// We could clear the failure count allowing the user to toggle wifi, then retry sign-in

View file

@ -116,13 +116,18 @@ namespace MatterHackers.MatterControl
mainContainer.AddChild(contentRow);
mainContainer.AddChild(footerRow);
mainContainer.Padding = new BorderDouble(3, 5, 3, 5);
headerRow.Padding = new BorderDouble(0, 3, 0, 3);
#if __ANDROID__
if (false)
#endif
{
mainContainer.Padding = new BorderDouble(3, 5, 3, 5);
headerRow.Padding = new BorderDouble(0, 3, 0, 3);
headerLabel.TextWidget.PointSize = 14;
headerLabel.TextColor = ActiveTheme.Instance.PrimaryTextColor;
contentRow.Padding = new BorderDouble(5);
footerRow.Margin = new BorderDouble(0, 3);
headerLabel.TextWidget.PointSize = 14;
headerLabel.TextColor = ActiveTheme.Instance.PrimaryTextColor;
contentRow.Padding = new BorderDouble(5);
footerRow.Margin = new BorderDouble(0, 3);
}
this.AddChild(mainContainer);
}

View file

@ -70,7 +70,7 @@ public class LicenseAgreementPage : DialogPage
protected override void OnCancel(out bool abortCancel)
{
// Exit if EULA is not accepted
UiThread.RunOnIdle(MatterControlApplication.Instance.Close);
UiThread.RunOnIdle(AppContext.RootSystemWindow.Close);
abortCancel = false;
}

View file

@ -74,7 +74,7 @@ namespace MatterHackers.MatterControl
nextButton.Visible = true;
skipButton.Visible = false;
configureButton.Visible = false;
MatterControlApplication.Instance.ConfigureWifi();
AppContext.Platform.ConfigureWifi();
});
};

View file

@ -98,7 +98,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
double value;
if (!double.TryParse(textValue, out value))
{
MatterControlApplication.BreakInDebugger("Slicing value is not a double.");
return valueOnError;
}

@ -1 +1 @@
Subproject commit e03d0344ceb98c59d24f916a9217c4a4fa0a32a1
Subproject commit 4a00055f6ed13dc4649d13c4cb499f3b7e09b202

View file

@ -45,6 +45,9 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />

View file

@ -59,7 +59,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
testRunner.CompleteDialog(
MatterControlUtilities.GetTestItemPath("Fennec_Fox.stl"));
// Wait up to 3 seconds for expected outcome
// Wait for expected outcome
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
// Assert - one part added and queue count increases by one
@ -93,7 +93,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
MatterControlUtilities.GetTestItemPath("Batman.stl")),
secondsToWait: 2);
// Wait up to 3 seconds for expected outcome
// Wait for expected outcome
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
// Assert - two parts added and queue count increases by two
@ -203,7 +203,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
testRunner.CompleteDialog(
MatterControlUtilities.GetTestItemPath("Rook.amf"));
// Wait up to 3 seconds for expected outcome
// Wait for expected outcome
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
// Assert - one part added and queue count increases by one
@ -233,7 +233,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
testRunner.CompleteDialog(
MatterControlUtilities.GetTestItemPath("Batman.stl"));
// Wait up to 3 seconds for expected outcome
// Wait for expected outcome
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
// Assert - one part added and queue count increases by one
@ -263,7 +263,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
testRunner.CompleteDialog(
MatterControlUtilities.GetTestItemPath("chichen-itza_pyramid.gcode"));
// Wait up to 3 seconds for expected outcome
// Wait for expected outcome
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
// Assert - one part added and queue count increases by one

View file

@ -573,7 +573,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
testRunner.Delay(2);
// Confirm abort
Assert.IsFalse(MatterControlApplication.Instance.HasBeenClosed, "Canceling Close dialog should *not* close MatterControl");
Assert.IsFalse(AppContext.RootSystemWindow.HasBeenClosed, "Canceling Close dialog should *not* close MatterControl");
// Close MatterControl and cancel print
testRunner.CloseMatterControl();
@ -587,7 +587,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
testRunner.Delay(2);
// Confirm close
Assert.IsTrue(MatterControlApplication.Instance.HasBeenClosed, "Confirming Close dialog *should* close MatterControl");
Assert.IsTrue(AppContext.RootSystemWindow.HasBeenClosed, "Confirming Close dialog *should* close MatterControl");
// Wait for M106 change
testRunner.WaitFor(() => fanChangedCount > 0, 15, 500);

View file

@ -3,4 +3,5 @@
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="NUnit.ApplicationDomain" version="11.0.0" targetFramework="net461" />
<package id="System.ValueTuple" version="4.4.0" targetFramework="net461" />
</packages>

View file

@ -68,7 +68,9 @@ namespace MatterHackers.MatterControl.Tests.Automation
private static string runName = DateTime.Now.ToString("yyyy-MM-ddTHH-mm-ss");
public static string PathToDownloadsSubFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads", "-Temporary");
private static SystemWindow rootSystemWindow;
public static void RemoveAllFromQueue(this AutomationRunner testRunner)
{
testRunner.ClickByName("Queue... Menu");
@ -137,7 +139,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
public static void CloseMatterControl(this AutomationRunner testRunner)
{
MatterControlApplication.Instance.Close();
rootSystemWindow?.Close();
}
public enum PrepAction
@ -579,10 +581,8 @@ namespace MatterHackers.MatterControl.Tests.Automation
UserSettings.Instance.set(UserSettingsKey.ThumbnailRenderingMode, "orthographic");
//GL.HardwareAvailable = false;
MatterControlApplication matterControlWindow = MatterControlApplication.CreateInstance(overrideWidth, overrideHeight);
var config = TestAutomationConfig.Load();
if (config.UseAutomationDialogs)
{
AggContext.Config.ProviderTypes.DialogProvider = "MatterHackers.Agg.Platform.AutomationDialogProvider, GuiAutomation";
@ -592,8 +592,14 @@ namespace MatterHackers.MatterControl.Tests.Automation
AutomationRunner.TimeToMoveMouse = config.TimeToMoveMouse;
AutomationRunner.UpDelaySeconds = config.MouseUpDelay;
var (width, height) = RootSystemWindow.GetStartupBounds();
rootSystemWindow = Application.LoadRootWindow(
overrideWidth == -1 ? width : overrideWidth,
overrideHeight == -1 ? height : overrideHeight);
await AutomationRunner.ShowWindowAndExecuteTests(
matterControlWindow,
rootSystemWindow,
testMethod,
maxTimeToRun,
defaultTestImages,
@ -605,9 +611,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
ApplicationController.Instance.ActivePrinter.Connection.Disable();
}
MatterControlApplication app = MatterControlApplication.Instance;
app.RestartOnClose = false;
app.Close();
rootSystemWindow.Close();
});
}

View file

@ -109,7 +109,7 @@ namespace MatterHackers.MatterControl.Plugins.BrailleBuilder
{
UiThread.RunOnIdle(() =>
{
MatterControlApplication.Instance.LaunchBrowser("https://en.wikipedia.org/wiki/Braille");
ApplicationController.Instance.LaunchBrowser("https://en.wikipedia.org/wiki/Braille");
});
};