Commit a6ceab45 authored by mdjones's avatar mdjones Committed by Commit bot

Support 3+ panels in the OverlayPanelManager

BUG=

Review-Url: https://codereview.chromium.org/2388793005
Cr-Commit-Position: refs/heads/master@{#422964}
parent 1cfe9539
......@@ -10,12 +10,14 @@ import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
import java.util.Comparator;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
/**
* Used to decide which panel should be showing on screen at any moment.
* NOTE(mdjones): Currently only supports two panels.
*/
public class OverlayPanelManager {
......@@ -29,6 +31,9 @@ public class OverlayPanelManager {
HIGH;
}
/** The initial size of the priority queue for suppressed panels. */
private static final int INITIAL_QUEUE_CAPACITY = 3;
/** A map of panels that this class is managing. */
private final Set<OverlayPanel> mPanelSet;
......@@ -38,9 +43,8 @@ public class OverlayPanelManager {
/**
* If a panel was being shown and another panel with higher priority was requested to show,
* the lower priority one is stored here.
* TODO(mdjones): This should be a list in the case that there are more than two panels.
*/
private OverlayPanel mSuppressedPanel;
private Queue<OverlayPanel> mSuppressedPanels;
/** When a panel is suppressed, this is the panel waiting for the close animation to finish. */
private OverlayPanel mPendingPanel;
......@@ -58,6 +62,15 @@ public class OverlayPanelManager {
* Default constructor.
*/
public OverlayPanelManager() {
mSuppressedPanels = new PriorityQueue<>(INITIAL_QUEUE_CAPACITY,
new Comparator<OverlayPanel>() {
@Override
public int compare(OverlayPanel p1, OverlayPanel p2) {
// The head of the queue is the smallest element, so subtract p1's priority
// from p2's priority.
return p2.getPriority().ordinal() - p1.getPriority().ordinal();
}
});
mPanelSet = new HashSet<>();
}
......@@ -79,8 +92,8 @@ public class OverlayPanelManager {
} else if (panel.getPriority().ordinal() > mActivePanel.getPriority().ordinal()) {
// If a panel with higher priority than the active one requests to be shown, suppress
// the active panel and show the requesting one.
// NOTE(mdjones): closePanel will trigger notifyPanelClosed.
// the active panel and show the requesting one. closePanel will trigger
// notifyPanelClosed.
mPendingPanel = panel;
mPendingReason = reason;
mActivePanel.closePanel(StateChangeReason.SUPPRESS, true);
......@@ -88,7 +101,7 @@ public class OverlayPanelManager {
} else if (panel.canBeSuppressed()) {
// If a panel was showing and the requesting panel has a lower priority, suppress it
// if possible.
mSuppressedPanel = panel;
if (!mSuppressedPanels.contains(panel)) mSuppressedPanels.add(panel);
}
}
......@@ -107,7 +120,7 @@ public class OverlayPanelManager {
if (reason == StateChangeReason.SUPPRESS) {
if (mActivePanel == panel) {
if (mActivePanel.canBeSuppressed()) {
mSuppressedPanel = mActivePanel;
mSuppressedPanels.add(mActivePanel);
}
mActivePanel = mPendingPanel;
mActivePanel.peekPanel(mPendingReason);
......@@ -118,12 +131,13 @@ public class OverlayPanelManager {
// Normal close panel flow.
if (panel == mActivePanel) {
mActivePanel = null;
if (mSuppressedPanel != null) {
mActivePanel = mSuppressedPanel;
if (!mSuppressedPanels.isEmpty()) {
mActivePanel = mSuppressedPanels.poll();
mActivePanel.peekPanel(StateChangeReason.UNSUPPRESS);
}
} else {
mSuppressedPanels.remove(panel);
}
mSuppressedPanel = null;
}
}
......@@ -136,6 +150,14 @@ public class OverlayPanelManager {
return mActivePanel;
}
/**
* @return The size of the suppressed panel queue.
*/
@VisibleForTesting
public int getSuppressedQueueSize() {
return mSuppressedPanels.size();
}
/**
* Destroy all panels owned by this manager.
*/
......@@ -145,7 +167,7 @@ public class OverlayPanelManager {
}
mPanelSet.clear();
mActivePanel = null;
mSuppressedPanel = null;
mSuppressedPanels.clear();
// Clear references to held resources.
mDynamicResourceLoader = null;
......
......@@ -199,7 +199,85 @@ public class OverlayPanelManagerTest extends InstrumentationTestCase {
lowPriorityPanel.closePanel(StateChangeReason.UNKNOWN, false);
highPriorityPanel.closePanel(StateChangeReason.UNKNOWN, false);
assertEquals(null, panelManager.getActivePanel());
assertEquals(0, panelManager.getSuppressedQueueSize());
}
@SmallTest
@Feature({"OverlayPanel"})
public void testSuppressedPanelPriority() {
Context context = getInstrumentation().getTargetContext();
OverlayPanelManager panelManager = new OverlayPanelManager();
OverlayPanel lowPriorityPanel =
new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, true);
OverlayPanel mediumPriorityPanel =
new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, true);
OverlayPanel highPriorityPanel =
new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
// Only one panel is showing, should be medium priority.
mediumPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
assertEquals(panelManager.getActivePanel(), mediumPriorityPanel);
// High priority should have taken preciedence.
highPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
assertEquals(panelManager.getActivePanel(), highPriorityPanel);
// Low priority will be suppressed; high priority should still be showing.
lowPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
assertEquals(panelManager.getActivePanel(), highPriorityPanel);
// Start closing panels.
highPriorityPanel.closePanel(StateChangeReason.UNKNOWN, false);
// After high priority is closed, the medium priority panel should be visible.
assertEquals(panelManager.getActivePanel(), mediumPriorityPanel);
mediumPriorityPanel.closePanel(StateChangeReason.UNKNOWN, false);
// Finally the low priority panel should be showing.
assertEquals(panelManager.getActivePanel(), lowPriorityPanel);
lowPriorityPanel.closePanel(StateChangeReason.UNKNOWN, false);
// All panels are closed now.
assertEquals(null, panelManager.getActivePanel());
assertEquals(0, panelManager.getSuppressedQueueSize());
}
@SmallTest
@Feature({"OverlayPanel"})
public void testSuppressedPanelOrder() {
Context context = getInstrumentation().getTargetContext();
OverlayPanelManager panelManager = new OverlayPanelManager();
OverlayPanel lowPriorityPanel =
new MockOverlayPanel(context, null, panelManager, PanelPriority.LOW, true);
OverlayPanel mediumPriorityPanel =
new MockOverlayPanel(context, null, panelManager, PanelPriority.MEDIUM, true);
OverlayPanel highPriorityPanel =
new MockOverlayPanel(context, null, panelManager, PanelPriority.HIGH, false);
// Odd ordering for showing panels should still produce ordered suppression.
highPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
lowPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
mediumPriorityPanel.requestPanelShow(StateChangeReason.UNKNOWN);
assertEquals(2, panelManager.getSuppressedQueueSize());
// Start closing panels.
highPriorityPanel.closePanel(StateChangeReason.UNKNOWN, false);
// After high priority is closed, the medium priority panel should be visible.
assertEquals(panelManager.getActivePanel(), mediumPriorityPanel);
mediumPriorityPanel.closePanel(StateChangeReason.UNKNOWN, false);
// Finally the low priority panel should be showing.
assertEquals(panelManager.getActivePanel(), lowPriorityPanel);
lowPriorityPanel.closePanel(StateChangeReason.UNKNOWN, false);
// All panels are closed now.
assertTrue(panelManager.getActivePanel() == null);
assertEquals(0, panelManager.getSuppressedQueueSize());
}
@SmallTest
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment