public bool Navigate(Type panelType, string panelId, Dictionary<string, object> arguments = null)
{
if (panelType == null)
{
throw new Exception("Panel type can't be null!");
}
// Make sure we send args along.
if (arguments == null)
{
arguments = new Dictionary<string, object>();
}
// Clear this value
m_finalNavigateHasShownMenu = false;
bool isExitingPanel = false;
StackItem navigateFromPanel = null;
StackItem panelToReduceMemory = null;
lock (m_panelStack)
{
// For now we can only do one animation at a time. So if we are doing something we
// must ignore this
if (m_state != State.Idle)
{
return false;
}
// The panel we will navigate to
StackItem navigateToPanel = null;
// First, check to see if we already have the panel
foreach (StackItem item in m_panelStack)
{
if(item.Panel.GetType() == panelType && item.Id == panelId)
{
// We found it.
isExitingPanel = true;
navigateToPanel = item;
break;
}
}
// If we didn't find it make a new panel.
if(navigateToPanel == null)
{
navigateToPanel = new StackItem();
navigateToPanel.Panel = (IPanel)Activator.CreateInstance(panelType);
navigateToPanel.Id = panelId;
}
// Check the type
PanelType newPanelType = GetPanelType(navigateToPanel.Panel);
// Second, Figure out what panel will be leaving.
if (m_screenMode == ScreenMode.Single)
{
// If we are in single mode it will be the panel from the top of the stack
if (m_panelStack.Count > 0)
{
navigateFromPanel = m_panelStack.Last();
}
}
else
{
// If we are in split mode it will be the panel we will replace.
// So go through the list backwards and find it.
foreach (StackItem item in m_panelStack.Reverse<StackItem>())
{
// If the are both subreddit panels or both not, we found the panel.
if (GetPanelType(item.Panel) == newPanelType)
{
navigateFromPanel = item;
break;
}
}
}
// We need to type of the leaving panel. If the panel is null this
// is the first navigation of a type, so we will just call it the content panel.
PanelType navigateFromPanelType = PanelType.ContentPanel;
if (navigateFromPanel != null)
{
navigateFromPanelType = GetPanelType(navigateFromPanel.Panel);
}
// Third, Setup the panel. If it already exits call activate instead of setup.
if (isExitingPanel)
{
navigateToPanel.Panel.OnPanelPulledToTop(arguments);
}
else
{
navigateToPanel.Panel.PanelSetup(this, arguments);
}
// Special case! If the UI is already shown then we should just return here.
if(navigateFromPanel != null && navigateFromPanel.Panel.GetType() == navigateToPanel.Panel.GetType() && navigateFromPanel.Id == navigateToPanel.Id)
{
return true;
}
// Last, add the panel to the bottom of the list.
// Note if this existing the panel will be in the list twice!
m_panelStack.Add(navigateToPanel);
// Report the view
App.BaconMan.TelemetryMan.ReportPageView(navigateToPanel.Panel.GetType().Name);
// Check if there is someone we should ask to reduce memory
if(m_panelStack.Count > (c_numberOfHistoryPagesBeforeMemoryReduce + 1))
{
panelToReduceMemory = m_panelStack[m_panelStack.Count - (c_numberOfHistoryPagesBeforeMemoryReduce +1)];
// This can only happen in split mode.
if(m_screenMode == ScreenMode.Split)
{
// We need to make sure this panel isn't visible
PanelType reducePanelType = GetPanelType(panelToReduceMemory.Panel);
for (int count = m_panelStack.Count - 1; count >= 0; count--)
{
// Find the first panel of this type and make sure it isn't this panel
StackItem item = m_panelStack[count];
if (GetPanelType(item.Panel) == reducePanelType)
{
if (item.Id.Equals(panelToReduceMemory.Id) && item.Panel.GetType() == panelToReduceMemory.Panel.GetType())
{
// This is the panel thus it is visible. Just null out the var
// and leave it alone.
// #todo! There is a bug here, any panel that is cleared here will never be
// asked to reduce its memory. This isn't a huge deal, but something we might
// want to fix later. This isn't a huge problem because on mobile this will never happen
// and the memory manager will start killing pages if memory gets too high.
panelToReduceMemory = null;
}
// If the first panel we found wasn't it then this panel
// isn't visible.
break;
}
}
}
}
// Animate the current panel out
PlayFadeAnimation(newPanelType, navigateFromPanelType, State.FadingOut);
}
// If we have a panel tell it we are leaving no under lock.
if (navigateFromPanel != null)
{
FireOnNavigateFrom(navigateFromPanel.Panel);
}
// If we have a panel to reduce memory, ask it to.
if (panelToReduceMemory != null)
{
FireOnReduceMemory(panelToReduceMemory.Panel);
}
return true;
}