using UnityEditor; using UnityEngine; using System; using System.Collections.Generic; using System.Linq; using Perforce.P4; using log4net; namespace P4Connect { public class ConnectionWizard : EditorWindow { private static readonly ILog log = LogManager.GetLogger(typeof (ConnectionWizard)); private static ConnectionWizard _window = null; [MenuItem("Assets/Perforce/Wizard", false, 100)] public static void ShowWindow() { _window = ConnectionWizard.GetWindow("Connection Wizard"); _window.name = "P4 Connection Wizard"; #if UNITY_5 _window.titleContent = new GUIContent("Wizard"); #else _window.title = "Wizard"; #endif _window.minSize = new UnityEngine.Vector2(400.0f, 400.0f); Config.Instance.DefaultConnection.FromConfig(); _window.Cfg = Config.Instance.DefaultConnection; // Split the "Server" field into it's components _window.Protocol = _window.Cfg.Protocol; _window.Host = _window.Cfg.Host; _window.Port = _window.Cfg.Port; } public static ConnectionWizard Window { get { return _window; } } // Close Wizard Windows if any exist (after restart or run/ pause) public static void CloseWindows() { ConnectionWizard[] windows = Resources.FindObjectsOfTypeAll(); if (windows != null) { foreach (var win in windows) { win.Close(); } } } public ConnectionConfig Cfg; private void OnDestroy() { if (_state == WizardState.Complete) { Config.Instance.DefaultConnection.ToConfig(); } Config.ConnectionWizardShowing = false; } void OnSelectionChange() { Repaint(); } private static readonly GUILayoutOption LabelWidth = GUILayout.Width(100.0f); private static readonly GUILayoutOption TextWidth = GUILayout.Width(150.0f); private static readonly GUILayoutOption PasswordWidth = GUILayout.Width(120.0f); private static readonly GUILayoutOption ButtonWidth = GUILayout.Width(100.0f); private static readonly GUILayoutOption CheckWidth = GUILayout.Width(32.0f); private static readonly GUILayoutOption ExpandField = GUILayout.ExpandWidth(true); private static readonly GUILayoutOption ExpandHeight = GUILayout.ExpandHeight(true); private static GUIStyle _leftStyle; private static GUIStyle _rightStyle; private static GUIStyle _titleStyle; private static GUIStyle _fatButtonStyle; private static GUIStyle _gButtonStyle; private static GUIStyle _rButtonStyle; private static GUIStyle _yButtonStyle; static Rect _userLocation; static Rect _workspaceLocation; static bool _stylesInitialized = false; // Static initializer called ONCE from OnGUI() after initialization private static void InitializeStyles() { GUI.skin = Config.GetP4Skin(); _leftStyle = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleLeft, name = "left" }; _rightStyle = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleRight, name = "right" }; _titleStyle = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.MiddleCenter, fontSize = 16, name = "title" }; _fatButtonStyle = GUI.skin.GetStyle("fatButton"); _gButtonStyle = GUI.skin.GetStyle("greenFatButton"); _rButtonStyle = GUI.skin.GetStyle("redFatButton"); _yButtonStyle = GUI.skin.GetStyle("yellowFatButton"); _stylesInitialized = true; } public static void Refresh() { if (_window != null) _window.Repaint(); } public static string LocalizedDataPath { get; set; } // Server pane string Protocol { get; set; } string Host { get; set; } string Port { get; set; } // New User pane string User1 { get; set; } string FullName { get; set; } string Email { get; set; } string Password1 { get; set; } string Password2 { get; set; } private User _user; // New workspace pane string Workspace1 { get; set; } string Location { get; set; } public bool NewUser = false; public bool NewWorkspace = false; public enum WizardState { Server, User, Password, Workspace, Complete } private WizardState _state = WizardState.Server; void OnGUI() { if (!_stylesInitialized) { InitializeStyles(); _stylesInitialized = true; } if (PasswordPrompt.Instance != null && PasswordPrompt.Active) { PasswordPrompt.Instance.Focus(); return; } if (Cfg == null) Close(); EditorGUILayout.BeginVertical("Box"); if (_state == WizardState.Server) { GUILayout.Label("Welcome to the P4Connect Setup Wizard", _titleStyle); GUILayout.Label("This assistant helps you set up a connection with a Perforce Server", _leftStyle); GUILayout.Label(" ", _leftStyle); GUILayout.Label("Type in the server connection settings:",_leftStyle); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Protocol:", _leftStyle, LabelWidth); Protocol = EditorGUILayout.TextField(Protocol, TextWidth); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Host:", _leftStyle, LabelWidth); Host = EditorGUILayout.TextField(Host, TextWidth, ExpandField); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Port number:", _leftStyle, LabelWidth); Port = EditorGUILayout.TextField(Port, TextWidth); EditorGUILayout.EndHorizontal(); } if (_state == WizardState.User || _state == WizardState.Password) { GUILayout.Label("Log In", _titleStyle); GUILayout.Label("Connect to the server with an existing or new user account.", _leftStyle); EditorGUILayout.BeginHorizontal(); NewUser = ! GUILayout.Toggle(! NewUser, "", CheckWidth); GUILayout.Label("Log in to server \"" + Cfg.Server + "\" with an existing user account", _leftStyle); EditorGUILayout.EndHorizontal(); EditorGUI.BeginDisabledGroup(NewUser); EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); GUILayout.Label("User:", LabelWidth); Cfg.User = EditorGUILayout.TextField(Cfg.User, TextWidth); if (Event.current.type == EventType.Repaint) { _userLocation = GUILayoutUtility.GetLastRect(); _userLocation.y -= _userLocation.size.y; } if (GUILayout.Button("Browse", EditorStyles.miniButton, TextWidth)) { PopupWindow.Show(_userLocation, new P4PopupUsers()); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { GUILayout.Label("Password:", LabelWidth); Cfg.Password = EditorGUILayout.PasswordField(Cfg.Password, PasswordWidth); } GUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); EditorGUI.EndDisabledGroup(); EditorGUILayout.BeginHorizontal(); NewUser = GUILayout.Toggle(NewUser, "", CheckWidth); GUILayout.Label("Create a new user account", _leftStyle); EditorGUILayout.EndHorizontal(); EditorGUI.BeginDisabledGroup(!NewUser); EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); GUILayout.Label("User:", _rightStyle, LabelWidth); User1 = EditorGUILayout.TextField(User1, TextWidth, ExpandField); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("", LabelWidth); GUILayout.Label("Name used to log in (no spaces allowed)", _leftStyle); EditorGUILayout.EndHorizontal(); GUILayout.Label("", LabelWidth); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Full name:", _rightStyle, LabelWidth); FullName = EditorGUILayout.TextField(FullName, TextWidth, ExpandField); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("", LabelWidth); GUILayout.Label("First and Last name", _leftStyle); EditorGUILayout.EndHorizontal(); GUILayout.Label("", LabelWidth); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Password*:", _rightStyle, LabelWidth); Password1 = EditorGUILayout.TextField(Password1, PasswordWidth); Password2 = EditorGUILayout.TextField(Password2, PasswordWidth); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("", LabelWidth); GUILayout.Label("Enter password twice", _leftStyle); EditorGUILayout.EndHorizontal(); GUILayout.Label("", LabelWidth); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Email Address:", _rightStyle, LabelWidth); Email = EditorGUILayout.TextField(Email, TextWidth, ExpandField); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("", LabelWidth); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("", LabelWidth); GUILayout.Label("* Passwords must be at least eight characters long\n and must contain upper and lower case letters,\n or letters plus one or more symbols or numbers.", ExpandHeight); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); EditorGUI.EndDisabledGroup(); } if (_state == WizardState.Workspace) { GUILayout.Label("Choose Workspace", _titleStyle); GUILayout.Label("Choose an existing workspace or create a new one.", _leftStyle); GUILayout.Label(""); EditorGUILayout.BeginHorizontal(); NewWorkspace = !GUILayout.Toggle(!NewWorkspace, "", CheckWidth); GUILayout.Label("Select a workspace that has already been set up for your computer:", _leftStyle); EditorGUILayout.EndHorizontal(); EditorGUI.BeginDisabledGroup(NewWorkspace); EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Workspace:", LabelWidth); Cfg.Workspace = EditorGUILayout.TextField(Cfg.Workspace, TextWidth); if (Event.current.type == EventType.Repaint) { _workspaceLocation = GUILayoutUtility.GetLastRect(); _workspaceLocation.y -= _workspaceLocation.size.y; } if (GUILayout.Button("Browse", EditorStyles.miniButton)) { PopupWindow.Show(_workspaceLocation, new P4PopupWorkspaces()); } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); EditorGUI.EndDisabledGroup(); EditorGUILayout.BeginHorizontal(); NewWorkspace = GUILayout.Toggle(NewWorkspace, "", CheckWidth); GUILayout.Label("Create a new workspace", _leftStyle); EditorGUILayout.EndHorizontal(); EditorGUI.BeginDisabledGroup(!NewWorkspace); EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Workspace:", _leftStyle, LabelWidth); Workspace1 = EditorGUILayout.TextField(Workspace1, TextWidth, ExpandField); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("", LabelWidth); GUILayout.Label("No spaces allowed in name", _leftStyle); EditorGUILayout.EndHorizontal(); GUILayout.Label(""); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Project Dir:", _leftStyle, LabelWidth); GUILayout.Label(Main.DataPath, _leftStyle, ExpandField); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Workspace Root:", _leftStyle, LabelWidth); Location = EditorGUILayout.TextField(Location, TextWidth, ExpandField); if (GUILayout.Button("Browse", EditorStyles.miniButton, ButtonWidth)) { GUI.FocusControl(""); string dir = Location.Length > 0 ? Location : Utils.AssetPathToFullPath(Main.RootPath); string path = EditorUtility.SaveFolderPanel("Set Workspace Root Directory", dir, ""); if (path.Length > 0) { Location = path; } } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("", LabelWidth); GUILayout.Label("The workspace Root must contain the project directory",_leftStyle); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); EditorGUI.EndDisabledGroup(); GUILayout.Label(""); GUILayout.Label("The workspace is where you keep local copies of the files managed by Perforce."); } if (_state == WizardState.Complete) { GUILayout.Label("Setup is now complete", _titleStyle); GUILayout.Label("P4Connect is using these settings", _leftStyle); GUILayout.Label(" ", _leftStyle); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Server:", _leftStyle, LabelWidth); GUILayout.Label(Cfg.Server); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("User:", _leftStyle, LabelWidth); GUILayout.Label(Cfg.User); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Workspace:", _leftStyle, LabelWidth); GUILayout.Label(Cfg.Workspace); EditorGUILayout.EndHorizontal(); GUILayout.Label(""); GUILayout.Label("To keep these settings, save them before continuing:"); if (GUILayout.Button("Save Settings", _gButtonStyle, TextWidth)) { Cfg.ToConfig(); if (Config.SaveMode == Config.SaveSettingsMode.EditorPrefs) { Config.WritePrefs(); } if (Config.SaveMode == Config.SaveSettingsMode.ConfigAsset) { Config.WriteConfigAsset(); } Config.Instance.LastSavedConnection = new ConnectionConfig(true); Close(); } } // Now we draw the button bar at the bottom GUILayout.FlexibleSpace(); // Horizontal bar GUILayout.Box("", new GUILayoutOption[] { GUILayout.ExpandWidth(true), GUILayout.Height(1)}); EditorGUILayout.BeginHorizontal(); { if (_state != WizardState.Complete) { if (GUILayout.Button("Help", _fatButtonStyle, ButtonWidth)) { OnHelp(); } GUILayout.FlexibleSpace(); if (GUILayout.Button("Back", _fatButtonStyle, ButtonWidth)) { OnBack(); } if (GUILayout.Button("Next", _gButtonStyle, ButtonWidth)) { OnNext(); } if (GUILayout.Button("Cancel", _rButtonStyle, ButtonWidth)) { OnCancel(); } } else { GUILayout.FlexibleSpace(); if (GUILayout.Button("Back", _fatButtonStyle, ButtonWidth)) { OnBack(); } if (GUILayout.Button("OK", _gButtonStyle, ButtonWidth)) { OnNext(); } } } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); } void OnHelp() { System.Diagnostics.Process.Start("http://www.perforce.com/perforce/doc.current/manuals/p4connectguide/index.html"); } void OnCancel() { Close(); } void OnBack() { switch (_state) { case WizardState.Server: { Close(); break; } case WizardState.User: { _state = WizardState.Server; break; } case WizardState.Password: { _state = WizardState.User; break; } case WizardState.Workspace: { _state = WizardState.Password; break; } case WizardState.Complete: { _state = WizardState.Workspace; break; } } } /// /// Transition dialog _state from current to the next. /// void OnNext() { Again: switch (_state) { case WizardState.Server: { Cfg.Server = ConnectionConfig.ServerFromPieces(Protocol, Host, Port); Cfg.ServerValid = GetServerInfo(); if (Cfg.ServerValid) { // generate default username if (!string.IsNullOrEmpty(Config.Username)) { Cfg.User = User1 = Config.Username; } else { Cfg.User = User1 = Environment.UserName.Replace(' ','_'); // No spaces in usernames } _state = WizardState.User; } break; } case WizardState.User: { if (NewUser) { if (ValidateNewUser()) { CreateNewUser(); _state = WizardState.Password; } } else { if (ValidateUser(Cfg.User)) { _state = WizardState.Password; } } if (_state == WizardState.Password) goto Again; break; } case WizardState.Password: { if (PasswordPrompt.Active) { PasswordPrompt.Instance.Focus(); break; } // Test username and password together here if (VerifySettings.CheckUsernamePassword(Cfg)) { _state = WizardState.Workspace; } else { VerifySettings.PromptForPassword(); } // Setup the workspace window if (_state == WizardState.Workspace) { Location = Main.RootPath; LocalizedDataPath = Utils.AssetPathToLocalPath(Main.RootPath); // See if we can find a matching default workspace Cfg.Workspace = GetDefaultWorkspace(Cfg, Cfg.User); NewWorkspace = (Cfg.Workspace.Length <= 0); // generate a workspace name for the new workspace Workspace1 = (Cfg.User + "_" + Main.ProjectName + "_" + Environment.MachineName).Replace(' ','_'); // No spaces in workspaces } break; } case WizardState.Workspace: { if (NewWorkspace) { if (ValidateNewWorkspace()) { if (CreateNewWorkspace()) { _state = WizardState.Complete; } } } else { if (ValidateWorkspace(Cfg.Workspace)) { _state = WizardState.Complete; } } break; } case WizardState.Complete: { Config.Valid = Config.CheckSettings(Cfg); if (Config.Valid) { Cfg.ToConfig(); } Config.ConnectionWizardShowing = false; break; } } } /// /// Check that an existing user exists /// /// name of user /// true if user exists bool ValidateUser(string username) { // Cfg.UserValid = VerifySettings.UserExists(Cfg, username); // // if (!Cfg.UserValid) // { // EditorUtility.DisplayDialog("User not found", "user " + username + " does not exist on server " + Cfg.Server, "ok"); // } // // return Cfg.UserValid; return true; } /// /// Check the validity of the New User dialog values /// /// bool ValidateNewUser() { string errorMessage = ""; // if (VerifySettings.UserExists(Cfg, User1)) // errorMessage = "User " + User1 + " already exists"; if (!Password1.Equals(Password2)) errorMessage = "Passwords do not match"; if (FullName.Length == 0) errorMessage = "FullName must not be empty"; if (Email.Length == 0) errorMessage = "Email must not be empty"; if (errorMessage.Length != 0) { EditorUtility.DisplayDialog("Can't create new user", errorMessage, "ok"); return false; } return true; } /// /// Create a new user using the current dialog values /// void CreateNewUser() { // Get a new user form from the server _user = VerifySettings.GetUser(Cfg, User1); // Update the user record with new information _user.Id = User1; _user.FullName = FullName; _user.EmailAddress = Email; _user.Password = Password1; // Then write the updated user back out. VerifySettings.SaveUser(Cfg, _user, UserSaveResponseDialog); } /// /// Check existing workspace name for validity /// /// workspace name /// bool ValidateWorkspace(string workspace) { if (VerifySettings.WorkspaceExists(Cfg, workspace)) return true; EditorUtility.DisplayDialog("Missing Workspace", "Workspace " + workspace + " does not exist on server " + Cfg.Server, "ok"); return false; } private static bool IsUsableWorkspace(Client c) { if (Utils.IsDirOrValidSubDirectoryOf(LocalizedDataPath, c.Root)) { return true; } return false; } /// /// Return the name of the first matching workspace (user and root must fit our project) /// /// connection info and user name /// username to filter workspaces with /// static string GetDefaultWorkspace(ConnectionConfig cfg, string user) { try { //Debug.Log("Getting default workspace for user: " + user + "cfg: " + cfg.ToString()); var clients = VerifySettings.GetWorkspacesByUser(cfg, user, WorkspaceBrowseResponse); if (clients != null) { foreach (var c in clients) { if (IsUsableWorkspace(c)) { //Debug.Log("Default workspace is: " + c.Name); return c.Name; } } } } catch (Exception ex) { Debug.Log("GetDefaultWorkspace Exception: " + ex.Message); } return ""; } /// /// Check New Workspace dialog values for validity /// /// bool ValidateNewWorkspace() { string errorMessage = ""; if (VerifySettings.WorkspaceExists(Cfg, Workspace1)) errorMessage = "A Workspace named " + Workspace1 + " already exists"; if (! Utils.IsDirOrValidSubDirectoryOf(Utils.AssetPathToFullPath(Main.DataPath), Utils.AssetPathToLocalPath(Location))) { errorMessage = "Workspace Root does not contain the project directory"; } if (errorMessage.Length != 0) { EditorUtility.DisplayDialog("Workspace Error", errorMessage, "ok"); return false; } return true; } /// /// Create a New workspace using the current dialog values /// bool CreateNewWorkspace() { // Create a new workspace on the server Client client = VerifySettings.GetWorkspace(Cfg, Workspace1, WorkspaceBrowseResponse); if (client != null) { // Update the user record with new information client.Name = Workspace1; client.Root = Location; client.Description = "Created by P4Connect wizard"; client.Options = ClientOption.None; // Then write the updated user back out. VerifySettings.SaveWorkspace(Cfg, client, WorkspaceBrowseResponse); Cfg.Workspace = client.Name; return true; } return false; } /// /// Test the Server URI and make sure it exists and is accessable /// Sets the static ServerInfo reference. /// /// true if command worked bool GetServerInfo() { try { VerifySettings.ServerInfoResult handler = ServerInfoResponse; return VerifySettings.CheckServerUri(Cfg, handler); } catch (Exception ex) { Debug.Log("Caught Exception: " + ex.Message); } return false; } /// /// Callback for GetServerInfo command. /// /// state of command /// current connection information /// error message returned static void ServerInfoResponse(bool result, ConnectionConfig cfg , string message) { string summary = result ? "Test Passed" : "Test Failed"; if (! result) EditorUtility.DisplayDialog(summary, message, "ok"); else { //Debug.Log("CaseSensitive: " + cfg.IsCaseSensitive ); //Debug.Log("Unicode: " + cfg.IsUnicode); } } static void UserBrowseResponse(bool result, string info) { string summary = result ? "Users Retrieved" : "Failed to retrieve users"; EditorUtility.DisplayDialog(summary, info, "ok"); } static void WorkspaceBrowseResponse(bool result, string info) { string summary = result ? "Workspaces Retrieved" : "No Workspaces"; EditorUtility.DisplayDialog(summary, info, "ok"); } /// /// Callback used when saving an updated user to server /// /// /// public static void UserSaveResponseDialog(bool result, string info) { string summary = result ? "User Saved" : "Failed to save user"; EditorUtility.DisplayDialog(summary, info, "ok"); } } public class P4PopupUsers : PopupWindowContent { private User[] _users; private string[] _names; private int _index; private bool _isEnabled; private bool _foundUser = false; private static GUIStyle _popupStyle; public ConnectionConfig Cfg { set; get; } public static void UserBrowseResponse(bool result, string info) { string summary = result ? "Users Retrieved" : "Failed to retrieve users"; EditorUtility.DisplayDialog(summary, info, "ok"); } public override Vector2 GetWindowSize() { return new Vector2(150, 20); } static bool _stylesInitialized = false; // Static initializer called ONCE from OnGUI() after initialization private static void InitializeStyles() { _popupStyle = new GUIStyle(EditorStyles.popup); _stylesInitialized = true; } public override void OnGUI(Rect location) { if (!_stylesInitialized) { InitializeStyles(); } if (_foundUser) { _index = EditorGUI.Popup(location, _index, _names, _popupStyle); } else { GUI.Label(location, "No users found"); } } public override void OnOpen() { if (!_isEnabled) { _isEnabled = true; Cfg = Config.Instance.DefaultConnection; IList users = new List(); try { users = VerifySettings.GetUsers(Cfg, UserBrowseResponse); } catch (Exception ex) { Debug.Log("GetUsers Exception: " + ex.Message); } if (users != null && users.Any()) { _foundUser = true; _users = users.ToArray(); _names = _users.Select(u => u.Id).ToArray(); } } } public override void OnClose() { if (_users != null && _users.Length > _index) OnSelection(_users[_index]); } void OnSelection(User u) { Config.Username = Cfg.User = u.Id; Cfg.UserValid = true; Cfg.PasswordValid = false; } } public class P4PopupWorkspaces : PopupWindowContent { private IList _clientList; private Client[] _clients; private string[] _names; private int _index; private bool _isEnabled; private static GUIStyle _popupStyle; private bool _foundWorkspace = false; private bool _clicked; public static string LocalizedDataPath { set; get; } public ConnectionConfig Cfg { set; get; } public static void WorkspaceBrowseResponse(bool result, string info) { string summary = result ? "Workspaces Retrieved" : "Failed to retrieve workspaces"; EditorUtility.DisplayDialog(summary, info, "ok"); } public override Vector2 GetWindowSize() { return new Vector2(150, 20); } static bool _stylesInitialized = false; // Static initializer called ONCE from OnGUI() after initialization private static void InitializeStyles() { _popupStyle = new GUIStyle(EditorStyles.popup); _stylesInitialized = true; } public override void OnGUI(Rect location) { if (!_stylesInitialized) { InitializeStyles(); } GUI.SetNextControlName("pop1"); if (_foundWorkspace) { _index = EditorGUI.Popup(location, _index, _names, _popupStyle); } else { GUI.Label(location, "No matching workspace found"); } if (!_clicked) { GUI.FocusControl("pop1"); _clicked = true; } } public override void OnOpen() { if (!_isEnabled) { _isEnabled = true; LocalizedDataPath = Utils.AssetPathToLocalPath(Main.DataPath); Cfg = Config.Instance.DefaultConnection; try { _clientList = VerifySettings.GetWorkspacesByUser(Cfg, Cfg.User, WorkspaceBrowseResponse); } catch (Exception ex) { Debug.Log("GetClients Exception: " + ex.Message); } if (_clientList != null && _clientList.Any()) { _clients = _clientList.Where(c => IsUsableWorkspace(c)).ToArray(); _names = _clients.Select(c => c.Name).ToArray(); _foundWorkspace = _names.Length > 0; } } } private static bool IsUsableWorkspace(Client c) { return Utils.IsDirOrValidSubDirectoryOf(LocalizedDataPath, c.Root); } public override void OnClose() { if (_foundWorkspace) { OnSelection(_clients[_index]); } } void OnSelection(Client c) { Config.Workspace = Cfg.Workspace = c.Name; Cfg.WorkspaceValid = true; } } }