Problem

Problems saving windows states with two monitors

Posted 28 days ago by Avatar Otavio Camargo

I'm getting some problems to keep ToolWindow states after saving it when using 2 monitors.

In the second monitor I have the main window with 3 docked panes.

In the first monitor I have a second window with 4 docked panes.

When the main window is closed, the windows state is saved and the program is closed.

After start the program up again, the main window in second monitor keeps the original state.

But the second window in firt monitor lose the width settings for some of docked panes.

Looking in the code, I couldn't find a place where the width and the height of the window are set.

How the ToolWindow calculate and keep height and width?

Bellow is the code for saving and load window state.

 

public void Save(bool closing = false)
{
var savedConfigs = new List<Modularization.Configuration.ModuleConfigurationBase>();

IEnumerable<ProfileContent> collection = _profileManager.GetProfilesAsync(COCKPIT_MAIN_STATE_KEY, true).Result.OrderByDescending(p => p.Timestamp);

ProfileContent content = collection.FirstOrDefault();

Task profileSyncTask = null;

if (content == null)
{
content = new ProfileContent();
content.Category = COCKPIT_MAIN_STATE_KEY;
}
else if (collection.Count() > 1)
{
foreach (var cockpitMainState in collection.Skip(1))
{
_profileManager.DeleteAsync(cockpitMainState);
}

if (!closing)
{
profileSyncTask = _profileManager.SyncRemoteProfilesAsync();
}
}

var state = new MainState();
state.Rectangle = new Rect(App.MainView.Left, App.MainView.Top, App.MainView.Width, App.MainView.Height);
state.WindowState = App.MainView.WindowState;
state.ToolAreaVisibility = App.MainView.ToolAreaVisibility;
state.Symbols.AddRange(App.MainView.GetSymbols());

if (App.MainView.ToolAreaMenuControl.CurrentToolAreaList != null)
{
state.SelectedToolAreaList = App.MainView.ToolAreaMenuControl.CurrentToolAreaList.MenuItem.Key;
}

foreach (var workspace in _workspaceController.Workspaces)
{
WorkspaceState workspaceState = null;

if (workspace.IsLoadedToolControls)
{
workspaceState = new WorkspaceState();

workspaceState.Order = workspace.Order;
workspaceState.IsCurrentWorkspace = workspace.IsCurrentWorkspace;
workspaceState.Name = workspace.WorkspaceName;
workspaceState.Data = GetDockSiteSerializer().SaveToString(workspace);
if (workspace.WindowProperties != null && workspace.WindowProperties.Count > 0)
workspaceState.WindowProperties = workspace.WindowProperties;

foreach (var window in workspace.ToolWindows.OfType<DockableWindow>())
{
if (window.InstanceId != Guid.Empty)
{
// Maps a dockable window (UniqueId) to a tool content (InstanceId);
workspaceState.DockableWindows.Add(window.UniqueId, window.InstanceId);

// Saves the internal tool state in the ToolState structure.
var toolState = new ToolState
{
CurrentChannel = window.CurrentChannel,
CurrentTarget = window.CurrentTarget,
InstanceId = window.InstanceId,
Key = window.ToolKey,
WindowState = window.ParentRaftingWindow != null ? window.ParentRaftingWindow.WindowState : WindowState.Normal,
IsFixed = window.CanDragToLinkedDockSites.HasValue ? window.CanDragToLinkedDockSites.Value : false
};

if (!BindingOperations.IsDataBound(window, DockableWindow.TitleProperty))
{
toolState.Title = window.Title;
}

bool saveToWorkspace;
var config = this.SaveState(toolState, window, out saveToWorkspace);

if (config != null && saveToWorkspace)
{
savedConfigs.Add(config);
}

if (saveToWorkspace)
{
workspaceState.Tools.Add(toolState.InstanceId, toolState);
}
}
}
}
else
{
workspace.State.Name = workspace.WorkspaceName;
workspaceState = workspace.State;

}

state.Workspaces.Add(workspaceState);
}

foreach (var gadget in _workspaceController.OpenedGadgetWindow)
{
var gadgetState = new ToolState
{
CurrentChannel = gadget.CurrentChannel,
CurrentTarget = gadget.CurrentTarget,
InstanceId = gadget.InstanceId,
Key = gadget.ToolKey,
WindowState = gadget.WindowState,
IsFixed = gadget.IsPinned,
WorkspaceOrder = gadget.WorkspaceOrder,
Rectangle = new Rect
{
X = gadget.Left,
Y = gadget.Top,
Width = gadget.ActualWidth,
Height = gadget.ActualHeight
}
};

bool saveToWorkspace;
var config = this.SaveState(gadgetState, gadget, out saveToWorkspace);

if (config != null && saveToWorkspace)
{
savedConfigs.Add(config);
}

if (saveToWorkspace)
{
state.Gadgets.Add(gadgetState);
}
}

content.Data = state;

if (profileSyncTask != null)
{
profileSyncTask.ContinueWith(t =>
{
_profileManager.SaveAsync(content, true, !closing).Wait();
_configurationManager.SaveLocalConfigurationsAsync(savedConfigs.ToArray()).Wait();
}).Wait();
}
else
{
_profileManager.SaveAsync(content, true, !closing).Wait();
_configurationManager.SaveLocalConfigurationsAsync(savedConfigs.ToArray()).Wait();
}
}

 

public void Load(ManualResetEventSlim baseDataSignal)
{
// Carregando configurações globais
var globalConfiguration = new GlobalConfiguration();

globalConfiguration.RegisterAppearance();

Task<GlobalConfigurationBase> getConfig = _configurationManager.GetGlobalConfigurationAsync(typeof(GlobalConfiguration));

Task<ProfileContent> getProfile = _profileManager.GetProfileAsync(COCKPIT_MAIN_STATE_KEY, true, true);

globalConfiguration = (GlobalConfiguration)getConfig.Result;
var content = getProfile.Result;

if (content != null && !content.HasErrors)
{
try
{
var state = content.Data as MainState;

if (state == null)
{
state = Valor.Core.SharedData.Serializer.Serializer.CleanDeserialize<MainState>(content.Data.ToString());
}

if (state != null)
{
LoadWorkspaces(state);

LoadStates(state.Workspaces.FirstOrDefault(i => i.IsCurrentWorkspace), state.Gadgets);

LoadWindows(state);
}
}
catch (Exception ex)
{
_log.Error("Error loading user state. Initializing with a clean workspace and state. Exception: {0}", ex);

LoadDefaultState();
}
}
else
{
LoadDefaultState();
}
}

 

private void LoadWindows(MainState state)
{
_dispatcher.Invoke(() =>
{
// Sets the current workspace in the main view. This is necessary because during the load,
// all workspaces are set as CurrentWorkspace, and the last one might not be the user's current
// workspace.
var currentWorkspaceState = state.Workspaces.FirstOrDefault(p => p.IsCurrentWorkspace);

if (currentWorkspaceState != null)
{
var currentWorkspace = _workspaceController.Workspaces.First(p => p.Order == currentWorkspaceState.Order);

_workspaceController.CurrentWorkspace = currentWorkspace;
}

// Restores the state of the MainView and its ToolArea.
App.MainView.ToolAreaVisibility = state.ToolAreaVisibility;
App.MainView.ToolAreaMenuControl.SetSelectedMenuItem(state.SelectedToolAreaList);
App.MainView.Left = state.Rectangle.Left;
App.MainView.Top = state.Rectangle.Top;
App.MainView.Width = state.Rectangle.Width;
App.MainView.Height = state.Rectangle.Height;
App.MainView.SetSymbols(state.Symbols);

// Restore the WindowState of all floating windows.
foreach (var workspaceState in state.Workspaces)
{
var workspace = _workspaceController.Workspaces.First(p => p.Order == workspaceState.Order);

foreach (var window in workspace.ToolWindows.OfType<DockableWindow>())
{
ToolState toolState;
if (workspaceState.Tools.TryGetValue(window.InstanceId, out toolState) && window.ParentRaftingWindow != null)
{
window.ParentRaftingWindow.WindowState = toolState.WindowState;
}
}
}

// Restore the WindowState of all gadgets.
foreach (var toolState in state.Gadgets)
{
var window = _workspaceController.OpenedGadgetWindow.FirstOrDefault(p => p.InstanceId == toolState.InstanceId);

if (window != null)
{
window.WindowState = toolState.WindowState;
}
}

App.MainView.Show();

App.MainView.WindowState = state.WindowState;
}, DispatcherPriority.Input);
}

Information The latest build of this product (2018.1 build 0673) was released 1 month ago, which was before this thread was created.

Comments (1)

Posted 28 days ago by Actipro Software Support - Cleveland, OH, USA

Hello,

I'm sorry you're having trouble.  Please first make sure you are on the most recent v2018.1 build (one came out this week) and see if it still happens there.  We've made a lot of adjustments to Docking/MDI over recent builds.  Let us know the result. 

Other than that, it's tough for us to say what's going on in a complex scenario like this without a simple example project to debug.  If you need further assistance, please make a new simple sample project that is as minimal as possible and shows the issue.  Then send that to our support address, mentioning this thread in the email.  We will debug with that project and see what's happening.  Please be sure to remove the bin/obj folders from the ZIP you send and rename the .zip file extension so it doesn't get spam blocked.  Thanks!


Actipro Software Support

Add a Comment

Please log in to a validated account to post comments.