# made tabs in AdminConsole scrollable

This commit is contained in:
Lukas Niemeier
2013-11-17 17:39:55 +01:00
parent ff80a1b196
commit 2d5befa3de
5 changed files with 386 additions and 77 deletions
@@ -4,17 +4,22 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor;
import com.sap.sailing.gwt.ui.client.AbstractEntryPoint;
import com.sap.sailing.gwt.ui.client.RegattaDisplayer;
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
import com.sap.sailing.gwt.ui.client.shared.controls.ScrolledTabLayoutPanel;
import com.sap.sailing.gwt.ui.client.shared.panels.SystemInformationPanel;
import com.sap.sailing.gwt.ui.client.shared.panels.UserStatusPanel;
import com.sap.sailing.gwt.ui.masterdataimport.MasterDataImportPanel;
@@ -22,135 +27,155 @@ import com.sap.sailing.gwt.ui.shared.RegattaDTO;
public class AdminConsoleEntryPoint extends AbstractEntryPoint implements RegattaRefresher {
private Set<RegattaDisplayer> regattaDisplayers;
private final AdminConsoleResources resources = GWT.create(AdminConsoleResources.class);
@Override
protected void doOnModuleLoad() {
super.doOnModuleLoad();
RootPanel rootPanel = RootPanel.get();
VerticalPanel verticalPanel = new VerticalPanel();
rootPanel.add(verticalPanel);
rootPanel.setSize("100%", "100%");
verticalPanel.setSize("100%", "100%");
RootLayoutPanel rootPanel = RootLayoutPanel.get();
DockLayoutPanel dockPanel = new DockLayoutPanel(Unit.EM);
rootPanel.add(dockPanel);
HorizontalPanel topInformationPanel = new HorizontalPanel();
topInformationPanel.setSize("100%", "95%");
UserStatusPanel userStatusPanel = new UserStatusPanel(userManagementService, this);
userStatusPanel.ensureDebugId("UserStatus");
topInformationPanel.add(userStatusPanel);
topInformationPanel.add(persistentAlertLabel);
verticalPanel.add(topInformationPanel);
TabPanel tabPanel = new TabPanel();
dockPanel.addNorth(topInformationPanel, 2.5);
TabLayoutPanel tabPanel = new ScrolledTabLayoutPanel(2.5, Unit.EM, resources.arrowLeft(), resources.arrowRight(), 200);
tabPanel.ensureDebugId("AdministrationTabs");
tabPanel.setAnimationEnabled(true);
tabPanel.setSize("99%", "95%");
verticalPanel.add(tabPanel); //, 10, 10);
regattaDisplayers = new HashSet<RegattaDisplayer>();
tabPanel.setAnimationDuration(500);
SailingEventManagementPanel sailingEventManagementPanel = new SailingEventManagementPanel(sailingService, this, stringMessages);
tabPanel.add(sailingEventManagementPanel, stringMessages.events(), false);
regattaDisplayers = new HashSet<RegattaDisplayer>();
RegattaStructureManagementPanel eventStructureManagementPanel = new RegattaStructureManagementPanel(sailingService, this, stringMessages, this);
//eventStructureManagementPanel.ensureDebugId("RegattaStructureManagement");
tabPanel.add(eventStructureManagementPanel, stringMessages.regattas());
SailingEventManagementPanel sailingEventManagementPanel = new SailingEventManagementPanel(sailingService, this,
stringMessages);
sailingEventManagementPanel.setSize("90%", "90%");
addScrollableTab(tabPanel, sailingEventManagementPanel, stringMessages.events());
RegattaStructureManagementPanel eventStructureManagementPanel = new RegattaStructureManagementPanel(
sailingService, this, stringMessages, this);
// eventStructureManagementPanel.ensureDebugId("RegattaStructureManagement");
eventStructureManagementPanel.setSize("90%", "90%");
addScrollableTab(tabPanel, eventStructureManagementPanel, stringMessages.regattas());
regattaDisplayers.add(eventStructureManagementPanel);
TracTracEventManagementPanel tractracEventManagementPanel = new TracTracEventManagementPanel(sailingService, this, this, stringMessages);
TracTracEventManagementPanel tractracEventManagementPanel = new TracTracEventManagementPanel(sailingService,
this, this, stringMessages);
tractracEventManagementPanel.ensureDebugId("TracTracEventManagement");
tractracEventManagementPanel.setSize("90%", "90%");
tabPanel.add(tractracEventManagementPanel, stringMessages.tracTracEvents(), false);
addScrollableTab(tabPanel, tractracEventManagementPanel, stringMessages.tracTracEvents());
regattaDisplayers.add(tractracEventManagementPanel);
SwissTimingReplayConnectorPanel swissTimingReplayConnectorPanel = new SwissTimingReplayConnectorPanel(sailingService, this, this, stringMessages);
SwissTimingReplayConnectorPanel swissTimingReplayConnectorPanel = new SwissTimingReplayConnectorPanel(
sailingService, this, this, stringMessages);
swissTimingReplayConnectorPanel.setSize("90%", "90%");
tabPanel.add(swissTimingReplayConnectorPanel, stringMessages.swissTimingArchiveConnector(), false);
addScrollableTab(tabPanel, swissTimingReplayConnectorPanel, stringMessages.swissTimingArchiveConnector());
regattaDisplayers.add(swissTimingReplayConnectorPanel);
SwissTimingEventManagementPanel swisstimingEventManagementPanel = new SwissTimingEventManagementPanel(sailingService, this, this, stringMessages);
//swisstimingEventManagementPanel.ensureDebugId("SwissTimingEventManagement");
SwissTimingEventManagementPanel swisstimingEventManagementPanel = new SwissTimingEventManagementPanel(
sailingService, this, this, stringMessages);
// swisstimingEventManagementPanel.ensureDebugId("SwissTimingEventManagement");
swisstimingEventManagementPanel.setSize("90%", "90%");
tabPanel.add(swisstimingEventManagementPanel, stringMessages.swissTimingEvents(), false);
addScrollableTab(tabPanel, swisstimingEventManagementPanel, stringMessages.swissTimingEvents());
regattaDisplayers.add(swisstimingEventManagementPanel);
CreateSwissTimingRacePanel createSwissTimingRacePanel = new CreateSwissTimingRacePanel(sailingService, this, stringMessages);
//createSwissTimingRacePanel.ensureDebugId("CreateSwissTimingRace");
CreateSwissTimingRacePanel createSwissTimingRacePanel = new CreateSwissTimingRacePanel(sailingService, this,
stringMessages);
// createSwissTimingRacePanel.ensureDebugId("CreateSwissTimingRace");
createSwissTimingRacePanel.setSize("90%", "90%");
tabPanel.add(createSwissTimingRacePanel,"Create SwissTiming race",false);
TrackedRacesManagementPanel trackedRacesManagementPanel = new TrackedRacesManagementPanel(sailingService, this, this, stringMessages);
//trackedRacesManagementPanel.ensureDebugId("TrackedRacesManagement");
addScrollableTab(tabPanel, createSwissTimingRacePanel, "Create SwissTiming race");
TrackedRacesManagementPanel trackedRacesManagementPanel = new TrackedRacesManagementPanel(sailingService, this,
this, stringMessages);
// trackedRacesManagementPanel.ensureDebugId("TrackedRacesManagement");
trackedRacesManagementPanel.setSize("90%", "90%");
tabPanel.add(trackedRacesManagementPanel, stringMessages.trackedRaces(),false);
addScrollableTab(tabPanel, trackedRacesManagementPanel, stringMessages.trackedRaces());
regattaDisplayers.add(trackedRacesManagementPanel);
final CompetitorPanel competitorPanel = new CompetitorPanel(sailingService, stringMessages, this);
//trackedRacesManagementPanel.ensureDebugId("TrackedRacesManagement");
// trackedRacesManagementPanel.ensureDebugId("TrackedRacesManagement");
trackedRacesManagementPanel.setSize("90%", "90%");
tabPanel.add(competitorPanel, stringMessages.competitors(), false);
RaceCourseManagementPanel raceCourseManagementPanel = new RaceCourseManagementPanel(sailingService, this, this, stringMessages);
//raceCourseManagementPanel.ensureDebugId("RaceCourseManagement");
addScrollableTab(tabPanel, competitorPanel, stringMessages.competitors());
RaceCourseManagementPanel raceCourseManagementPanel = new RaceCourseManagementPanel(sailingService, this, this,
stringMessages);
// raceCourseManagementPanel.ensureDebugId("RaceCourseManagement");
raceCourseManagementPanel.setSize("90%", "90%");
tabPanel.add(raceCourseManagementPanel, stringMessages.courseLayout(),false);
addScrollableTab(tabPanel, raceCourseManagementPanel, stringMessages.courseLayout());
regattaDisplayers.add(raceCourseManagementPanel);
final AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor();
WindPanel windPanel = new WindPanel(sailingService, asyncActionsExecutor, this, this, stringMessages);
//windPanel.ensureDebugId("WindManagement");
// windPanel.ensureDebugId("WindManagement");
regattaDisplayers.add(windPanel);
windPanel.setSize("90%", "90%");
tabPanel.add(windPanel, stringMessages.wind(), /* asHTML */ false);
final LeaderboardGroupConfigPanel leaderboardGroupConfigPanel = new LeaderboardGroupConfigPanel(sailingService, this, this, stringMessages);
//leaderboardGroupConfigPanel.ensureDebugId("LeaderboardGroupConfiguration");
addScrollableTab(tabPanel, windPanel, stringMessages.wind());
final LeaderboardGroupConfigPanel leaderboardGroupConfigPanel = new LeaderboardGroupConfigPanel(sailingService,
this, this, stringMessages);
// leaderboardGroupConfigPanel.ensureDebugId("LeaderboardGroupConfiguration");
leaderboardGroupConfigPanel.setSize("90%", "90%");
tabPanel.add(leaderboardGroupConfigPanel, stringMessages.leaderboardGroupConfiguration(), /*asHTML*/ false);
addScrollableTab(tabPanel, leaderboardGroupConfigPanel, stringMessages.leaderboardGroupConfiguration());
regattaDisplayers.add(leaderboardGroupConfigPanel);
final LeaderboardConfigPanel leaderboardConfigPanel = new LeaderboardConfigPanel(sailingService, this, this, stringMessages,
/* showRaceDetails */ true);
final LeaderboardConfigPanel leaderboardConfigPanel = new LeaderboardConfigPanel(sailingService, this, this,
stringMessages,
/* showRaceDetails */true);
leaderboardConfigPanel.ensureDebugId("LeaderboardConfiguration");
leaderboardConfigPanel.setSize("90%", "90%");
tabPanel.add(leaderboardConfigPanel, stringMessages.leaderboardConfiguration(), /* asHTML */ false);
addScrollableTab(tabPanel, leaderboardConfigPanel, stringMessages.leaderboardConfiguration());
regattaDisplayers.add(leaderboardConfigPanel);
tabPanel.add(new ResultImportUrlsManagementPanel(sailingService, this, stringMessages), stringMessages.resultImportUrls(), /* asHTML */ false);
addScrollableTab(tabPanel, new ResultImportUrlsManagementPanel(sailingService, this, stringMessages),
stringMessages.resultImportUrls());
ReplicationPanel replicationPanel = new ReplicationPanel(sailingService, this, stringMessages);
//replicationPanel.ensureDebugId("ReplicationManagement");
tabPanel.add(replicationPanel, stringMessages.replication(), /* asHTML */ false);
// replicationPanel.ensureDebugId("ReplicationManagement");
addScrollableTab(tabPanel, replicationPanel, stringMessages.replication());
final MediaPanel mediaPanel = new MediaPanel(mediaService, this, stringMessages);
tabPanel.add(mediaPanel, stringMessages.mediaPanel(), /* asHTML */ false);
final MasterDataImportPanel masterDataImportPanel = new MasterDataImportPanel(stringMessages, sailingService, this, sailingEventManagementPanel, leaderboardGroupConfigPanel);
tabPanel.add(masterDataImportPanel, stringMessages.masterDataImportPanel(), /* asHTML */ false);
final DeviceConfigurationPanel deviceConfigurationPanel = new DeviceConfigurationPanel(sailingService, stringMessages, this);
tabPanel.add(deviceConfigurationPanel, stringMessages.deviceConfiguration(), false);
addScrollableTab(tabPanel, mediaPanel, stringMessages.mediaPanel());
final MasterDataImportPanel masterDataImportPanel = new MasterDataImportPanel(stringMessages, sailingService,
this, sailingEventManagementPanel, leaderboardGroupConfigPanel);
addScrollableTab(tabPanel, masterDataImportPanel, stringMessages.masterDataImportPanel());
final DeviceConfigurationPanel deviceConfigurationPanel = new DeviceConfigurationPanel(sailingService,
stringMessages, this);
addScrollableTab(tabPanel, deviceConfigurationPanel, stringMessages.deviceConfiguration());
tabPanel.selectTab(0);
tabPanel.addSelectionHandler(new SelectionHandler<Integer>() {
@Override
public void onSelection(SelectionEvent<Integer> event) {
if (leaderboardConfigPanel.isVisible()) {
leaderboardConfigPanel.loadLeaderboards();
}
}
if (mediaPanel.isVisible()) {
mediaPanel.onShow();
}
if (competitorPanel.isVisible()) {
competitorPanel.refreshCompetitorList();
}
}
}
});
fillRegattas();
SystemInformationPanel sysinfoPanel = new SystemInformationPanel(sailingService, this);
sysinfoPanel.ensureDebugId("SystemInformation");
verticalPanel.add(sysinfoPanel);
dockPanel.addSouth(sysinfoPanel, 2.0);
dockPanel.add(tabPanel);
}
private void addScrollableTab(TabLayoutPanel tabPanel, Widget widget, String tabTitle) {
ScrollPanel widgetScroller = new ScrollPanel();
widgetScroller.add(widget);
tabPanel.add(widgetScroller, tabTitle, false);
}
@Override
@@ -40,4 +40,10 @@ interface AdminConsoleResources extends ClientBundle {
@Source("com/sap/sailing/gwt/ui/client/images/reddot.png")
ImageResource reddotIcon();
@Source("com/sap/sailing/gwt/ui/client/images/arrow_left.png")
ImageResource arrowLeft();
@Source("com/sap/sailing/gwt/ui/client/images/arrow_right.png")
ImageResource arrowRight();
}
@@ -0,0 +1,278 @@
package com.sap.sailing.gwt.ui.client.shared.controls;
import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* A {@link TabLayoutPanel} that shows scroll buttons if necessary. Stolen from the internets and adapted.
*/
public class ScrolledTabLayoutPanel extends TabLayoutPanel {
private static final int SCROLL_RIGHT_TAB_MARGIN = 10;
private static final int SCROLL_ANIMATION_SPEED = 150;
private LayoutPanel panel;
private FlowPanel tabBar;
private Widget scrollLeftWidget;
private Widget scrollRightWidget;
private HandlerRegistration windowResizeHandler;
private boolean isScrolling = false;
private final ImageResource leftArrowImage;
private final ImageResource rightArrowImage;
private final int scrollSpeed;
private final double barHeight;
private final Unit barUnit;
public ScrolledTabLayoutPanel(double barHeight, Unit barUnit, ImageResource leftArrowImage,
ImageResource rightArrowImage) {
this(barHeight, barUnit, leftArrowImage, rightArrowImage, 100);
}
public ScrolledTabLayoutPanel(double barHeight, Unit barUnit, ImageResource leftArrowImage,
ImageResource rightArrowImage, int scrollSpeed) {
super(barHeight, barUnit);
this.leftArrowImage = leftArrowImage;
this.rightArrowImage = rightArrowImage;
this.scrollSpeed = scrollSpeed;
this.barHeight = barHeight;
this.barUnit = barUnit;
// The main widget wrapped by this composite, which is a LayoutPanel with the tab bar & the tab content
panel = (LayoutPanel) getWidget();
// Find the tab bar, which is the first flow panel in the LayoutPanel
for (int i = 0; i < panel.getWidgetCount(); ++i) {
Widget widget = panel.getWidget(i);
if (widget instanceof FlowPanel) {
tabBar = (FlowPanel) widget;
break; // tab bar found
}
}
initScrollButtons();
}
@Override
public void add(Widget child, Widget tab) {
super.add(child, tab);
checkIfScrollButtonsNecessary();
}
@Override
public boolean remove(Widget w) {
boolean b = super.remove(w);
checkIfScrollButtonsNecessary();
return b;
}
@Override
protected void onLoad() {
super.onLoad();
if (windowResizeHandler == null) {
windowResizeHandler = Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
checkIfScrollButtonsNecessary();
}
});
}
checkIfScrollButtonsNecessary();
}
@Override
protected void onUnload() {
super.onUnload();
if (windowResizeHandler != null) {
windowResizeHandler.removeHandler();
windowResizeHandler = null;
}
}
private ClickHandler createScrollClickHandler(final int diff) {
return new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
int difference = diff;
Widget lastTab = getLastTab();
if (lastTab == null)
return;
int oldLeft = parsePosition(tabBar.getElement().getStyle().getLeft());
if (getAbsoluteRightOfTabBar() < getAbsoluteRightOfWidget(lastTab)) {
// Prevent over-scrolling right-most tab
difference = Math.max(difference,
(getAbsoluteRightOfTabBar() - getAbsoluteRightOfWidget(lastTab) - SCROLL_RIGHT_TAB_MARGIN));
}
// Prevent over-scrolling left border
int newLeft = Math.min(oldLeft + difference, 0);
scrollTo(oldLeft, newLeft);
}
};
}
private Widget centerVertical(Widget widget) {
VerticalPanel vertical = new VerticalPanel();
vertical.setSize("100%", "100%");
vertical.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
DOM.setStyleAttribute(vertical.getElement(), "backgroundColor", "#ccc");
DOM.setStyleAttribute(vertical.getElement(), "marginTop", "6px");
vertical.add(widget);
return vertical;
}
/** Create and attach the scroll button images with a click handler */
private void initScrollButtons() {
Image scrollLeftButton = new Image(leftArrowImage);
scrollLeftWidget = centerVertical(scrollLeftButton);
panel.insert(scrollLeftWidget, 0);
panel.setWidgetLeftWidth(scrollLeftWidget, 0, Unit.PX, scrollLeftButton.getWidth(), Unit.PX);
panel.setWidgetTopHeight(scrollLeftWidget, 0, Unit.PX, barHeight, barUnit);
scrollLeftButton.addClickHandler(createScrollClickHandler(+scrollSpeed));
scrollLeftWidget.setVisible(false);
Image scrollRightButton = new Image(rightArrowImage);
scrollRightWidget = centerVertical(scrollRightButton);
panel.insert(scrollRightWidget, 0);
panel.setWidgetRightWidth(scrollRightWidget, 0, Unit.PX, scrollRightButton.getWidth(), Unit.PX);
panel.setWidgetTopHeight(scrollRightWidget, 0, Unit.PX, barHeight, barUnit);
scrollRightButton.addClickHandler(createScrollClickHandler(-scrollSpeed));
scrollRightWidget.setVisible(false);
}
private void checkIfScrollButtonsNecessary() {
// Defer size calculations until sizes are available, when calculating immediately after
// add(), all size methods return zero
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute() {
boolean needsScrollingToRight = isScrollingToRightNecessary();
boolean needsScrollingToLeft = isScrollingToLeftNecessary();
// When the scroll buttons are being hidden, reset the scroll position to zero to
// make sure no tabs are still out of sight
if (scrollRightWidget.isVisible() && !needsScrollingToLeft && !needsScrollingToRight) {
resetScrollPosition();
}
scrollLeftWidget.setVisible(needsScrollingToLeft);
scrollRightWidget.setVisible(needsScrollingToRight);
}
});
}
private void resetScrollPosition() {
scrollTo(0, 0);
}
private void scrollTo(final int oldPos, final int newPos) {
if (isScrolling) {
return;
}
isScrolling = true;
final int difference = newPos - oldPos;
new Animation() {
@Override
protected void onUpdate(double progress) {
tabBar.getElement().getStyle().setLeft(oldPos + (interpolate(progress) * difference), Unit.PX);
}
@Override
protected void onComplete() {
super.onComplete();
checkIfScrollButtonsNecessary();
isScrolling = false;
}
}.run(SCROLL_ANIMATION_SPEED);
}
private boolean isScrollingToRightNecessary() {
Widget lastTab = getLastTab();
if (lastTab == null)
return false;
return getAbsoluteRightOfWidget(lastTab) > getAbsoluteRightOfTabBar();
}
private boolean isScrollingToLeftNecessary() {
Widget firstTab = getFirstTab();
if (firstTab == null)
return false;
return getAbsoluteLeftOfWidget(firstTab) < getAbsoluteLeftOfTabBar();
}
private int getAbsoluteLeftOfTabBar() {
return tabBar.getElement().getParentElement().getAbsoluteLeft();
}
private int getAbsoluteRightOfTabBar() {
return tabBar.getElement().getParentElement().getAbsoluteRight();
}
private int getAbsoluteLeftOfWidget(Widget widget) {
return widget.getElement().getAbsoluteLeft();
}
private int getAbsoluteRightOfWidget(Widget widget) {
return widget.getElement().getAbsoluteRight();
}
private Widget getLastTab() {
if (tabBar.getWidgetCount() == 0)
return null;
return tabBar.getWidget(tabBar.getWidgetCount() - 1);
}
private Widget getFirstTab() {
if (tabBar.getWidgetCount() == 0)
return null;
return tabBar.getWidget(0);
}
private static int parsePosition(String positionString) {
int position;
try {
for (int i = 0; i < positionString.length(); i++) {
char c = positionString.charAt(i);
if (c != '-' && !(c >= '0' && c <= '9')) {
positionString = positionString.substring(0, i);
}
}
position = Integer.parseInt(positionString);
} catch (NumberFormatException ex) {
position = 0;
}
return position;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B