refactoring of UI-components for the race board

- CollapsablePanel as base class for the raceboard panels
This commit is contained in:
fmittag committed 2012-01-18 17:33:05 +01:00
1 parent 362968224c
commit b5ed17701b
14 files changed
+812 -68

No files matched your search

@@ -0,0 +1,70 @@
package com.sap.sailing.gwt.ui.raceboard;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.components.CollapsablePanel;
import com.sap.sailing.gwt.ui.shared.components.Component;
import com.sap.sailing.gwt.ui.shared.components.ComponentGroup;
import com.sap.sailing.gwt.ui.shared.components.ComponentToolbar;
/**
* A GWT component that visualizes a {@link Component} or a {@link Component} including menus to scroll quickly to the embedded view
* of the respective component, collapse/expand buttons for the views embedded and homogeneous settings buttons for
* those components that have settings.
*
* @author Axel Uhl (d043530)
*
*/
public class CollapsableComponentViewer {
private final CollapsablePanel disclosurePanel;
private final Component<?> component;
private final StringMessages stringMessages;
public CollapsableComponentViewer(Component<?> component, StringMessages stringMessages) {
this.component = component;
this.stringMessages = stringMessages;
AbsolutePanel contentPanel = new AbsolutePanel();
disclosurePanel = createDisclosePanel(contentPanel, component.getLocalizedShortName(), 150);
}
public Widget getViewerWidget() {
return disclosurePanel;
}
public Component<?> getComponent() {
return component;
}
private CollapsablePanel createDisclosePanel(Panel contentPanel, String panelTitle, int heightInPx)
{
CollapsablePanel disclosurePanel = new CollapsablePanel (panelTitle);
disclosurePanel.setSize("100%", "100%");
disclosurePanel.setOpen(true);
ComponentToolbar toolbar = new ComponentToolbar(component, stringMessages);
toolbar.addSettingsButton();
disclosurePanel.setHeaderToolbar(toolbar);
contentPanel.setSize("100%", heightInPx + "px");
disclosurePanel.setContent(contentPanel);
if(component.getEntryWidget() != null) {
contentPanel.add(component.getEntryWidget());
} else {
if(component instanceof ComponentGroup) {
Iterable<Component<?>> components = ((ComponentGroup<?>) component).getComponents();
for(Component<?> c: components) {
if(c.getEntryWidget() != null)
contentPanel.add(c.getEntryWidget());
}
}
}
return disclosurePanel;
}
}
@@ -1,26 +1,19 @@
package com.sap.sailing.gwt.ui.raceboard;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.DisclosurePanel;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.adminconsole.RaceMap;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.Timer;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel;
import com.sap.sailing.gwt.ui.shared.components.Component;
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
import com.sap.sailing.server.api.DefaultLeaderboardName;
public class RaceBoardPanel extends FormPanel implements Component<RaceBoardSettings> {
@@ -28,66 +21,54 @@ public class RaceBoardPanel extends FormPanel implements Component<RaceBoardSett
private final ErrorReporter errorReporter;
// TODO Frank to use these later
// private final StringMessages stringMessages;
private String raceBoardName;
private static RaceBoardResources resources = GWT.create(RaceBoardResources.class);
// TODO Frank to use these later
// private List<DisclosurePanel> collapsablePanels;
private final CompetitorSelectionProvider competitorSelectionProvider;
private final List<CollapsableComponentViewer> collapsableViewers;
public RaceBoardPanel(SailingServiceAsync sailingService, String raceBoardName, ErrorReporter errorReporter,
final StringMessages stringMessages) {
this.sailingService = sailingService;
this.setRaceBoardName(raceBoardName);
this.errorReporter = errorReporter;
// TODO Frank to use these later
// this.stringMessages = stringMessages;
VerticalPanel mainPanel = new VerticalPanel();
mainPanel.setSize("100%", "100%");
setWidget(mainPanel);
competitorSelectionProvider = new CompetitorSelectionModel(/* hasMultiSelection */ true);
RaceMap raceMap = new RaceMap(sailingService, errorReporter, new Timer(
/* delayBetweenAutoAdvancesInMilliseconds */500), competitorSelectionProvider, stringMessages);
for(int i = 0; i < 4; i++) {
if(i == 0) {
AbsolutePanel contentPanel = new AbsolutePanel();
DisclosurePanel panel = createDisclosePanel(contentPanel, "Panel " + i, 300);
raceMap.loadMapsAPI(contentPanel);
mainPanel.add(panel);
} else {
VerticalPanel contentPanel = new VerticalPanel();
DisclosurePanel panel = createDisclosePanel(contentPanel, "Panel " + i, 100);
contentPanel.add(new Label("Content of panel " + i));
mainPanel.add(panel);
collapsableViewers = new ArrayList<CollapsableComponentViewer>();
for(int i = 0; i < 4; i++)
{
if(i == 0)
{
CompetitorSelectionModel competitorSelectionModel = new CompetitorSelectionModel(/* hasMultiSelection */ true);
//final RaceMapPanel raceMapPanel = new RaceMapPanel(sailingService, competitorSelectionModel, this, this, stringMessages);
LeaderboardPanel defaultLeaderboardPanel = new LeaderboardPanel(sailingService, competitorSelectionModel,
DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME, errorReporter, stringMessages);
CollapsableComponentViewer viewer = new CollapsableComponentViewer(defaultLeaderboardPanel, stringMessages);
collapsableViewers.add(viewer);
}
else
{
SimpleComponentGroup<Object> componentGroup = new SimpleComponentGroup<Object>("Component Group " + i);
componentGroup.addComponent(new SimpleComponent("My Component"));
componentGroup.addComponent(new SimpleComponent("My Component 2"));
componentGroup.addComponent(new SimpleComponent("My Component 3"));
//LeaderboardPanel leaderboardPanel = LeaderboardPanel();
CollapsableComponentViewer viewer = new CollapsableComponentViewer(componentGroup, stringMessages);
collapsableViewers.add(viewer);
}
}
}
private DisclosurePanel createDisclosePanel(Panel contentPanel, String panelTitle, int heightInPx) {
DisclosurePanel disclosurePanel = new DisclosurePanel (resources.openIcon(), resources.closeIcon(), panelTitle);
disclosurePanel.setSize("100%", "100%");
disclosurePanel.setOpen(true);
contentPanel.setSize("100%", heightInPx + "px");
disclosurePanel.setContent(contentPanel);
disclosurePanel.addOpenHandler(new OpenHandler<DisclosurePanel>() {
@Override
public void onOpen(OpenEvent<DisclosurePanel> event) {
}
});
disclosurePanel.addCloseHandler(new CloseHandler<DisclosurePanel>() {
@Override
public void onClose(CloseEvent<DisclosurePanel> event) {
}
});
return disclosurePanel;
for (CollapsableComponentViewer viewer : collapsableViewers) {
mainPanel.add(viewer.getViewerWidget());
}
}
@Override
@@ -130,3 +111,4 @@ public class RaceBoardPanel extends FormPanel implements Component<RaceBoardSett
return null;
}
}
@@ -11,4 +11,6 @@ interface RaceBoardResources extends ClientBundle {
@Source("com/sap/sailing/gwt/ui/client/images/close.png")
ImageResource closeIcon();
@Source("com/sap/sailing/gwt/ui/client/images/settings.png")
ImageResource settingsIcon();
}
@@ -0,0 +1,43 @@
package com.sap.sailing.gwt.ui.raceboard;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.shared.components.Component;
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
public class SimpleComponent implements Component<SimpleComponentSettings> {
private String componentName;
private final Label label;
public SimpleComponent(String componentName) {
this.componentName = componentName;
label = new Label("Ich bin eine Label component");
}
@Override
public String getLocalizedShortName() {
return componentName;
}
@Override
public Widget getEntryWidget() {
return label;
}
@Override
public boolean hasSettings() {
return true;
}
@Override
public SettingsDialogComponent<SimpleComponentSettings> getSettingsDialogComponent() {
return null;
}
@Override
public void updateSettings(SimpleComponentSettings newSettings) {
}
}
@@ -0,0 +1,62 @@
package com.sap.sailing.gwt.ui.raceboard;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.shared.components.Component;
import com.sap.sailing.gwt.ui.shared.components.ComponentGroup;
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
public class SimpleComponentGroup<SettingsType> implements ComponentGroup<SettingsType> {
private String groupName;
private final List<Component<?>> components;
public SimpleComponentGroup(String groupName) {
this.groupName = groupName;
components = new ArrayList<Component<?>>();
}
@Override
public boolean hasSettings() {
return false;
}
@Override
public SettingsDialogComponent<SettingsType> getSettingsDialogComponent() {
return null;
}
@Override
public void updateSettings(SettingsType newSettings) {
}
@Override
public String getLocalizedShortName() {
return groupName;
}
@Override
public Widget getEntryWidget() {
return null;
}
@Override
public boolean addComponent(Component<?> component) {
return components.add(component);
}
@Override
public boolean removeComponent(Component<?> component) {
return components.remove(component);
}
@Override
public Iterable<Component<?>> getComponents() {
return components;
}
}
@@ -0,0 +1,5 @@
package com.sap.sailing.gwt.ui.raceboard;
public class SimpleComponentSettings {
}
@@ -0,0 +1,427 @@
package com.sap.sailing.gwt.ui.shared.components;
import java.util.Iterator;
import com.google.gwt.animation.client.Animation;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasCloseHandlers;
import com.google.gwt.event.logical.shared.HasOpenHandlers;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
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.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HasAnimation;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* A widget that consists of a header and a content panel that discloses the content when a user clicks on the header.
*
* <h3>CSS Style Rules</h3>
* <dl class="css">
* <dt>.gwt-DisclosurePanel
* <dd>the panel's primary style
* <dt>.gwt-DisclosurePanel-open
* <dd>dependent style set when panel is open
* <dt>.gwt-DisclosurePanel-closed
* <dd>dependent style set when panel is closed
* </dl>
* <p>
* The header and content sections can be easily selected using css with a child selector:<br/>
* .gwt-DisclosurePanel-open .header { ... }
* </p>
*/
public final class CollapsablePanel extends Composite implements HasWidgets.ForIsWidget, HasAnimation,
HasOpenHandlers<CollapsablePanel>, HasCloseHandlers<CollapsablePanel> {
private static ComponentResources resources = GWT.create(ComponentResources.class);
/**
* Used to wrap widgets in the header to provide click support. Effectively wraps the widget in an
* <code>anchor</code> to get automatic keyboard access.
*/
private final class ClickableHeader extends SimplePanel {
private ClickableHeader() {
// Anchor is used to allow keyboard access.
super(DOM.createAnchor());
Element elem = getElement();
DOM.setElementProperty(elem, "href", "javascript:void(0);");
// Avoids layout problems from having blocks in inlines.
DOM.setStyleAttribute(elem, "display", "block");
sinkEvents(Event.ONCLICK);
setStyleName(STYLENAME_HEADER);
}
@Override
public void onBrowserEvent(Event event) {
// no need to call super.
switch (DOM.eventGetType(event)) {
case Event.ONCLICK:
// Prevent link default action.
DOM.eventPreventDefault(event);
setOpen(!isOpen);
}
}
}
/**
* An {@link Animation} used to open the content.
*/
private static class ContentAnimation extends Animation {
/**
* Whether the item is being opened or closed.
*/
private boolean opening;
/**
* The {@link CollapsablePanel} being affected.
*/
private CollapsablePanel curPanel;
/**
* Open or close the content.
*
* @param panel
* the panel to open or close
* @param animate
* true to animate, false to open instantly
*/
public void setOpen(CollapsablePanel panel, boolean animate) {
// Immediately complete previous open
cancel();
// Open the new item
if (animate) {
curPanel = panel;
opening = panel.isOpen;
run(ANIMATION_DURATION);
} else {
panel.contentWrapper.setVisible(panel.isOpen);
if (panel.isOpen) {
// Special treatment on the visible case to ensure LazyPanel works
panel.getContent().setVisible(true);
}
}
}
@Override
protected void onComplete() {
if (!opening) {
curPanel.contentWrapper.setVisible(false);
}
DOM.setStyleAttribute(curPanel.contentWrapper.getElement(), "height", "auto");
curPanel = null;
}
@Override
protected void onStart() {
super.onStart();
if (opening) {
curPanel.contentWrapper.setVisible(true);
// Special treatment on the visible case to ensure LazyPanel works
curPanel.getContent().setVisible(true);
}
}
@Override
protected void onUpdate(double progress) {
int scrollHeight = DOM.getElementPropertyInt(curPanel.contentWrapper.getElement(), "scrollHeight");
int height = (int) (progress * scrollHeight);
if (!opening) {
height = scrollHeight - height;
}
height = Math.max(height, 1);
DOM.setStyleAttribute(curPanel.contentWrapper.getElement(), "height", height + "px");
DOM.setStyleAttribute(curPanel.contentWrapper.getElement(), "width", "auto");
}
}
public interface Imager {
Image makeImage();
void updateImage(boolean open, Image image);
}
/**
* The duration of the animation.
*/
private static final int ANIMATION_DURATION = 350;
// Stylename constants.
private static final String STYLENAME_DEFAULT = "gwt-DisclosurePanel";
private static final String STYLENAME_SUFFIX_OPEN = "open";
private static final String STYLENAME_SUFFIX_CLOSED = "closed";
private static final String STYLENAME_HEADER = "header";
private static final String STYLENAME_CONTENT = "content";
/**
* The {@link Animation} used to open and close the content.
*/
private static ContentAnimation contentAnimation;
/**
* top level widget. The first child will be a reference to {@link #header}. The second child will be a reference to
* {@link #contentWrapper}.
*/
private final VerticalPanel mainPanel = new VerticalPanel();
/**
* The wrapper around the content widget.
*/
private final SimplePanel contentWrapper = new SimplePanel();
/**
* holds the header widget.
*/
private final DockPanel header = new DockPanel();
private final ClickableHeader clickableHeader = new ClickableHeader();
private boolean isAnimationEnabled = false;
private boolean isOpen = false;
/**
* Creates an empty ThePanel that is initially closed.
*/
private CollapsablePanel() {
initWidget(mainPanel);
header.setStyleName("hallo");
mainPanel.add(header);
mainPanel.add(contentWrapper);
DOM.setStyleAttribute(contentWrapper.getElement(), "padding", "0px");
DOM.setStyleAttribute(contentWrapper.getElement(), "overflow", "hidden");
setStyleName(STYLENAME_DEFAULT);
setContentDisplay(false);
}
/**
* Creates a ThePanel with the specified header text, an initial open/close state and a bundle of images to be used
* in the default header widget.
*
* @param openImage
* the open state image resource
* @param closedImage
* the closed state image resource
* @param headerText
* the text to be displayed in the header
*/
public CollapsablePanel(ImageResource openImage, ImageResource closedImage, String headerText) {
this();
setClickableHeader(new CollapsablePanelDefaultHeader(this, openImage, closedImage, headerText));
}
/**
* Creates a ThePanel that will be initially closed using the specified text in the header.
*
* @param headerText
* the text to be displayed in the header
*/
public CollapsablePanel(String headerText) {
this(resources.openIcon(), resources.closeIcon(), headerText);
}
private void setClickableHeader(Widget widget) {
clickableHeader.add(widget);
header.add(clickableHeader, DockPanel.WEST);
}
public void setHeaderToolbar(HorizontalPanel toolbar) {
header.add(toolbar, DockPanel.EAST);
}
public void add(Widget w) {
if (this.getContent() == null) {
setContent(w);
} else {
throw new IllegalStateException("A DisclosurePanel can only contain two Widgets.");
}
}
/**
* Overloaded version for IsWidget.
*
* @see #add(Widget)
*/
public void add(IsWidget w) {
this.add(asWidgetOrNull(w));
}
public HandlerRegistration addCloseHandler(CloseHandler<CollapsablePanel> handler) {
return addHandler(handler, CloseEvent.getType());
}
public HandlerRegistration addOpenHandler(OpenHandler<CollapsablePanel> handler) {
return addHandler(handler, OpenEvent.getType());
}
public void clear() {
setContent(null);
}
/**
* Gets the widget that was previously set in {@link #setContent(Widget)}.
*
* @return the panel's current content widget
*/
public Widget getContent() {
return contentWrapper.getWidget();
}
/**
* Gets the widget that is currently being used as a header.
*
* @return the widget currently being used as a header
*/
public Widget getHeader() {
return header.asWidget();
}
/**
* Gets a {@link HasText} instance to provide access to the headers's text, if the header widget does provide such
* access.
*
* @return a reference to the header widget if it implements {@link HasText}, <code>null</code> otherwise
*/
public HasText getHeaderTextAccessor() {
Widget widget = header.asWidget();
return (widget instanceof HasText) ? (HasText) widget : null;
}
public boolean isAnimationEnabled() {
return isAnimationEnabled;
}
/**
* Determines whether the panel is open.
*
* @return <code>true</code> if panel is in open state
*/
public boolean isOpen() {
return isOpen;
}
public Iterator<Widget> iterator() {
return null;
// return WidgetIterators.createWidgetIterator(this,
// new Widget[] {getContent()});
}
public boolean remove(Widget w) {
if (w == getContent()) {
setContent(null);
return true;
}
return false;
}
/**
* Overloaded version for IsWidget.
*
* @see #remove(Widget)
*/
public boolean remove(IsWidget w) {
return this.remove(asWidgetOrNull(w));
}
public void setAnimationEnabled(boolean enable) {
isAnimationEnabled = enable;
}
/**
* Sets the content widget which can be opened and closed by this panel. If there is a preexisting content widget,
* it will be detached.
*
* @param content
* the widget to be used as the content panel
*/
public void setContent(Widget content) {
final Widget currentContent = getContent();
// Remove existing content widget.
if (currentContent != null) {
contentWrapper.setWidget(null);
currentContent.removeStyleName(STYLENAME_CONTENT);
}
// Add new content widget if != null.
if (content != null) {
contentWrapper.setWidget(content);
content.addStyleName(STYLENAME_CONTENT);
setContentDisplay(false);
}
}
/**
* Changes the visible state of this <code>ThePanel</code>.
*
* @param isOpen
* <code>true</code> to open the panel, <code>false</code> to close
*/
public void setOpen(boolean isOpen) {
if (this.isOpen != isOpen) {
this.isOpen = isOpen;
setContentDisplay(true);
fireEvent();
}
}
/**
* <b>Affected Elements:</b>
* <ul>
* <li>-header = the clickable header.</li>
* </ul>
*
* @see UIObject#onEnsureDebugId(String)
*/
@Override
protected void onEnsureDebugId(String baseID) {
super.onEnsureDebugId(baseID);
header.ensureDebugId(baseID + "-header");
}
private void fireEvent() {
if (isOpen) {
OpenEvent.fire(this, this);
} else {
CloseEvent.fire(this, this);
}
}
private void setContentDisplay(boolean animate) {
if (isOpen) {
removeStyleDependentName(STYLENAME_SUFFIX_CLOSED);
addStyleDependentName(STYLENAME_SUFFIX_OPEN);
} else {
removeStyleDependentName(STYLENAME_SUFFIX_OPEN);
addStyleDependentName(STYLENAME_SUFFIX_CLOSED);
}
if (getContent() != null) {
if (contentAnimation == null) {
contentAnimation = new ContentAnimation();
}
contentAnimation.setOpen(this, animate && isAnimationEnabled);
}
}
}
@@ -0,0 +1,99 @@
package com.sap.sailing.gwt.ui.shared.components;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.shared.components.CollapsablePanel.Imager;
/**
* The default header widget used within a {@link CollapsablePanel}.
*/
public class CollapsablePanelDefaultHeader extends Widget implements HasText, OpenHandler<CollapsablePanel>,
CloseHandler<CollapsablePanel> {
/**
* imageTD holds the image for the icon, not null. labelTD holds the text for the label.
*/
private final Element labelTD;
private final Image iconImage;
private final Imager imager;
private final CollapsablePanel collapsablePanel;
protected CollapsablePanelDefaultHeader(CollapsablePanel collapsablePanel, Imager imager, String text) {
this.imager = imager;
this.collapsablePanel = collapsablePanel;
iconImage = imager.makeImage();
// I do not need any Widgets here, just a DOM structure.
Element root = DOM.createTable();
Element tbody = DOM.createTBody();
Element tr = DOM.createTR();
final Element imageTD = DOM.createTD();
labelTD = DOM.createTD();
setElement(root);
DOM.appendChild(root, tbody);
DOM.appendChild(tbody, tr);
DOM.appendChild(tr, imageTD);
DOM.appendChild(tr, labelTD);
// set image TD to be same width as image.
DOM.setElementProperty(imageTD, "align", "center");
DOM.setElementProperty(imageTD, "valign", "middle");
DOM.setStyleAttribute(imageTD, "width", iconImage.getWidth() + "px");
DOM.appendChild(imageTD, iconImage.getElement());
setText(text);
collapsablePanel.addOpenHandler(this);
collapsablePanel.addCloseHandler(this);
setStyle();
}
protected CollapsablePanelDefaultHeader(CollapsablePanel collapsablePanel, final ImageResource openImage,
final ImageResource closedImage, String text) {
this(collapsablePanel, new Imager() {
public Image makeImage() {
return new Image(closedImage);
}
public void updateImage(boolean open, Image image) {
if (open) {
image.setResource(openImage);
} else {
image.setResource(closedImage);
}
}
}, text);
}
public final String getText() {
return DOM.getInnerText(labelTD);
}
public final void onClose(CloseEvent<CollapsablePanel> event) {
setStyle();
}
public final void onOpen(OpenEvent<CollapsablePanel> event) {
setStyle();
}
public final void setText(String text) {
DOM.setInnerText(labelTD, text);
}
private void setStyle() {
imager.updateImage(collapsablePanel.isOpen(), iconImage);
}
}
@@ -1,5 +1,7 @@
package com.sap.sailing.gwt.ui.shared.components;
import com.google.gwt.user.client.ui.Widget;
/**
*
* @author Axel Uhl (d043530)
@@ -8,23 +10,17 @@ package com.sap.sailing.gwt.ui.shared.components;
* the type that describes this component's settings (if any). Use {@link Object} in case your components
* doesn't support any settings.
*/
public interface Component<SettingsType> extends ComponentForestEntry {
public interface Component<SettingsType> extends ComponentSettings<SettingsType> {
/**
* @return whether this component has settings that a user may change; if so,
* @return the name to display to a user for quick navigation to this component
*/
boolean hasSettings();
String getLocalizedShortName();
/**
* If this component {@link #hasSettings has settings}, this method may return a component for the settings dialog.
* It will be used to obtain a widget shown in the settings dialog, a validator for the component-specific settings,
* as well as to produce a result from the widget's state when the settings dialog wants to validate or return the
* settings.
* A component may or may not have a {@link Widget} used to render its contents. Typically,
* entries with sub-entries don't afford a widget of their own but let the framework choose a container
* in which to aggregate their entries' widgets.
*/
SettingsDialogComponent<SettingsType> getSettingsDialogComponent();
/**
* Updates the settings of this component. Expected to be called when a settings dialog using this component's
* {@link #getSettingsDialogComponent()} has been confirmed.
*/
void updateSettings(SettingsType newSettings);
Widget getEntryWidget();
}
@@ -0,0 +1,10 @@
package com.sap.sailing.gwt.ui.shared.components;
public interface ComponentGroup<SettingsType> extends Component<SettingsType> {
boolean addComponent(Component<?> component);
boolean removeComponent(Component<?> component);
Iterable<Component<?>> getComponents();
}
@@ -0,0 +1,16 @@
package com.sap.sailing.gwt.ui.shared.components;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;
interface ComponentResources extends ClientBundle {
@Source("com/sap/sailing/gwt/ui/client/images/open.png")
ImageResource openIcon();
@Source("com/sap/sailing/gwt/ui/client/images/close.png")
ImageResource closeIcon();
@Source("com/sap/sailing/gwt/ui/client/images/settings.png")
ImageResource settingsIcon();
}
@@ -0,0 +1,30 @@
package com.sap.sailing.gwt.ui.shared.components;
/**
*
* @author Axel Uhl (d043530)
*
* @param <SettingsType>
* the type that describes this component's settings (if any). Use {@link Object} in case your components
* doesn't support any settings.
*/public interface ComponentSettings<SettingsType> {
/**
* @return whether this component has settings that a user may change; if so,
*/
boolean hasSettings();
/**
* If this component {@link #hasSettings has settings}, this method may return a component for the settings dialog.
* It will be used to obtain a widget shown in the settings dialog, a validator for the component-specific settings,
* as well as to produce a result from the widget's state when the settings dialog wants to validate or return the
* settings.
*/
SettingsDialogComponent<SettingsType> getSettingsDialogComponent();
/**
* Updates the settings of this component. Expected to be called when a settings dialog using this component's
* {@link #getSettingsDialogComponent()} has been confirmed.
*/
void updateSettings(SettingsType newSettings);
}
@@ -46,6 +46,7 @@
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='components'/>
<source path='adminconsole'/>
<source path='leaderboard'/>
<source path='shared'/>
@@ -34,6 +34,7 @@
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='raceboard'/>
<source path='leaderboard'/>
<source path='adminconsole'/>
<source path='shared'/>
</module>