Rescued tabbar widget from old event series branch

This commit is contained in:
Papick Garcia Taboada committed 2015-02-02 16:48:19 +01:00
1 parent 854727e281
commit 13ad88beba
9 files changed
+572

No files matched your search

@@ -0,0 +1,35 @@
@CHARSET "UTF-8";
.event_header__breadcrumb {
font-size: 15px;
font-size: 1rem;
font-size: 0.866666666666667em;
font-weight: 600;
padding: 0.666666666666667em 0;
}
.event_header__breadcrumb__item {
position: relative;
display: inline-block;
padding-left: 1.923076923076923em;
color: #666;
}
.event_header__breadcrumb__item:before {
content: ' ';
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAUCAYAAAC58NwRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2OUUzNjU2OTYyN0ExMUU0OTkzRUFBMUUyRUFGQjM4NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2OUUzNjU2QTYyN0ExMUU0OTkzRUFBMUUyRUFGQjM4NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjY5RTM2NTY3NjI3QTExRTQ5OTNFQUExRTJFQUZCMzg3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY5RTM2NTY4NjI3QTExRTQ5OTNFQUExRTJFQUZCMzg3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+yfJlBgAAAK5JREFUeNpinDlz5goGBgZXIM4F4mUMBAATEDsBsRAQLwLiKGI0RADxdyBmJkYTSMM+IPYkVhMTlD5IrCYmJDZRmpjQ+CBNbvg0MWGx9Qg+TUw4/IZTExOeEIRp+oKkSZeJgTTAhk+DDRBvB2IeIP4LxIlAfJaJBMWLQRIsOBTvAmJOdMXYPI1XMboGe0KKkTXYQ92MVzFyfiBKMUzDCmIVI+eHd0AcR0gxCAAEGACmPjby/HEDIgAAAABJRU5ErkJggg==");
height: 100%;
width: 6px;
position: absolute;
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
left: 0.666666666666667em;
}
.event_header__breadcrumb__item:first-of-type {
padding-left: 0;
}
.event_header__breadcrumb__item:first-of-type:before {
display: none;
}
@@ -0,0 +1,74 @@
package com.sap.sse.gwt.client.controls.tabbar;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Widget;
/**
* @author zhorvath
*
*/
public class BreadcrumbPane extends Widget {
interface Resources extends ClientBundle {
@Source("Breadcrumb.css")
Style style();
}
interface Style extends CssResource {
String event_header__breadcrumb();
String event_header__breadcrumb__item();
}
private static Resources resources;
private static Resources getResources() {
if (resources == null) {
resources = GWT.create(Resources.class);
resources.style().ensureInjected();
}
return resources;
}
private final Style style = getResources().style();
private final DivElement breadcrumDiv;
public BreadcrumbPane() {
breadcrumDiv = Document.get().createDivElement();
breadcrumDiv.addClassName(style.event_header__breadcrumb());
setElement(breadcrumDiv);
}
public void addBreadcrumbItem(String title, String link, final Runnable runnable) {
AnchorElement breadcrumItem = Document.get().createAnchorElement();
breadcrumItem.setHref(link);
breadcrumItem.setInnerText(title);
breadcrumItem.addClassName(style.event_header__breadcrumb__item());
breadcrumDiv.appendChild(breadcrumItem);
Event.sinkEvents(breadcrumItem, Event.ONCLICK);
Event.setEventListener(breadcrumItem, new EventListener() {
@Override
public void onBrowserEvent(Event event) {
if (event.getTypeInt() == Event.ONCLICK) {
event.stopPropagation();
event.preventDefault();
runnable.run();
}
}
});
}
}
@@ -0,0 +1,6 @@
package com.sap.sse.gwt.client.controls.tabbar;
public interface PlaceContextProvider<PLACECONTEXT> {
PLACECONTEXT getContext();
}
@@ -0,0 +1,35 @@
package com.sap.sse.gwt.client.controls.tabbar;
import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
/**
* Defines lifecycle handling for the Activity.
* <p/>
* <p/>
* Created by pgtaboada on 25.11.14.
*/
public interface TabActivity<PLACE extends Place, PLACECONTEXT> {
/**
* The place type that activates this tab.
*
* @return
*/
Class<PLACE> getPlaceClassForActivation();
/**
* Initiates the tab lifecycle.
*
* @param placeToGo
* @param contentArea
*/
void start(PLACE requestedPlace, AcceptsOneWidget contentArea);
/**
* Tells the tab that it is going to be deactiviated (not visible anymore), because of tab switch
*/
void stop();
PLACE placeToFire(PLACECONTEXT ctx);
}
@@ -0,0 +1,34 @@
@CHARSET "UTF-8";
.nav-bar {
font-size: 15px;
font-size: 1rem;
}
.nav-bar__button {
font-size: 1.2em;
display: inline-block;
font-weight: 600;
color: #666;
border: 1px solid #dedede;
padding: 0.833333333333333em 0.944444444444444em;
background-color: #eee;
-webkit-transition: background-color 0.2s, border-color 0.2s;
transition: background-color 0.2s, border-color 0.2s;
text-decoration: none;
margin-right: 0.833333333333333em;
}
.nav-bar__button:hover,
.nav-bar__button:focus {
background-color: #dedede;
outline: none;
text-decoration: none;
}
.nav-bar__button--active {
color: #333;
background-color: #fff;
border-bottom: 1px solid #fff;
}
.nav-bar__button--active:hover {
background-color: #dedede;
border-bottom: 1px solid #dedede;
}
@@ -0,0 +1,143 @@
package com.sap.sse.gwt.client.controls.tabbar;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.place.shared.Place;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
/**
* Capsulates functionality for a tab bar.
*
* @author zhorvath
*
*/
public class TabBar extends Widget implements HasSelectionHandlers<Class<Place>> {
interface Resources extends ClientBundle {
@Source("TabBar.css")
Style style();
}
interface Style extends CssResource {
@ClassName("nav-bar")
String tabBar();
@ClassName("nav-bar__button")
String tab();
@ClassName("nav-bar__button--active")
String selected();
}
private static Resources resources;
private static Resources getResources() {
if (resources == null) {
resources = GWT.create(Resources.class);
resources.style().ensureInjected();
}
return resources;
}
private final Style style = getResources().style();
private final List<Class<Place>> places = new ArrayList<>();
private final DivElement tabBarDiv;
public TabBar() {
tabBarDiv = Document.get().createDivElement();
tabBarDiv.addClassName(style.tabBar());
setElement(tabBarDiv);
sinkEvents(Event.ONCLICK);
}
@Override
public void onBrowserEvent(Event event) {
EventTarget eventTarget = event.getEventTarget();
if (Element.is(eventTarget)) {
// An event target can be any JavaScript object, but we are interested in events related to DOM events only
Element element = eventTarget.cast();
if (event.getTypeInt() == Event.ONCLICK) {
// The user clicked somewhere into the tab bar -> we have to find the tab that was clicked
for (int i = 0; i < tabBarDiv.getChildCount(); i++) {
if (tabBarDiv.getChild(i).isOrHasChild(element)) {
event.stopPropagation();
event.preventDefault();
// the specific tab was clicked -> fire SelectionEvent with the associated place
GWT.log("Found " + places.get(i));
SelectionEvent.fire(this, places.get(i));
break;
}
}
}
}
super.onBrowserEvent(event);
}
/**
* Selects the tab associated with the given place.
*
* @param place
* the place that should get selected.
*/
public void select(Class<Place> place) {
GWT.log("Should activate: " + place.getName());
// remove all previous selections
for (int i = 0; i < tabBarDiv.getChildCount(); i++) {
Element.as(tabBarDiv.getChild(i)).removeClassName(style.selected());
}
// find the tab that has to be selected for the given place
for (int i = 0; i < places.size(); i++) {
if (place.equals(places.get(i))) {
GWT.log("Activate: " + place.getName());
// found the associated tab -> set the selected style.
Element.as(tabBarDiv.getChild(i)).addClassName(style.selected());
}
}
}
/**
* Adds a tab with an associated place to be fired when the tab is selected
*
* TODO: create custom widget for tab
*
* @param title
* the label of the tab header.
* @param place
* the place that should be associated with the tab.
*/
public void addTab(String title, Class<Place> place, String link) {
AnchorElement tabElement = Document.get().createAnchorElement();
tabElement.setHref(link);
tabElement.setInnerText(title);
tabElement.addClassName(style.tab());
tabBarDiv.appendChild(tabElement);
places.add(place);
}
/** {@inheritDoc} */
@Override
public HandlerRegistration addSelectionHandler(SelectionHandler<Class<Place>> handler) {
return addHandler(handler, SelectionEvent.getType());
}
}
@@ -0,0 +1,148 @@
package com.sap.sse.gwt.client.controls.tabbar;
import java.util.HashMap;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceHistoryMapper;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
/**
* Defines whole layout for site, including the header with the breadcrumbs and tab bar, and the content.
* <p/>
* Created by pgtaboada on 25.11.14.
*/
public class TabPanel<PLACECONTEXT> extends Composite {
private static TabPanelUiBinder ourUiBinder = GWT.create(TabPanelUiBinder.class);
private final Map<Class<Place>, TabActivity<Place, PLACECONTEXT>> knownTabs = new HashMap<>();
@UiField
AnchorElement back;
@UiField
SimplePanel additionalHeader;
@UiField
SimplePanel tabContentPanelUi;
@UiField
TabBar tabBar;
private TabActivity<Place, PLACECONTEXT> currentTab;
private final PlaceContextProvider<PLACECONTEXT> contextProvider;
private final PlaceHistoryMapper historyMapper;
public TabPanel(PlaceContextProvider<PLACECONTEXT> contextProvider, PlaceHistoryMapper historyMapper) {
this.contextProvider = contextProvider;
this.historyMapper = historyMapper;
initWidget(ourUiBinder.createAndBindUi(this));
}
public TabActivity<?, PLACECONTEXT> getCurrentTab() {
return currentTab;
}
@UiChild
public void addHeader(Widget widget) {
additionalHeader.setWidget(widget);
}
public void setBackAction(String link, final Runnable action) {
back.setHref(link);
back.getStyle().clearDisplay();
Event.sinkEvents(back, Event.ONCLICK);
Event.setEventListener(back, new EventListener() {
@Override
public void onBrowserEvent(Event event) {
event.preventDefault();
event.stopPropagation();
action.run();
}
});
}
/**
* Adds all tabs to the tab bar.
*
* @param tab
* The tab to add
* @param title
* The label for the tab.
*/
@UiChild
public void addTabContent(final TabActivity<Place, PLACECONTEXT> tab, String title) {
GWT.log("Adding TAB: " + title);
// TODO: check if place class already known, reject...
knownTabs.put(tab.getPlaceClassForActivation(), tab);
String link = "#" + historyMapper.getToken(tab.placeToFire(contextProvider.getContext()));
tabBar.addTab(title, tab.getPlaceClassForActivation(), link);
}
/**
* Handles given SelectionEvent, when tab is clicked. Fires a TabPanelPlaceSelectionEvent. The listener to this
* event should properly fire place change events.
*
* @param event
*/
@UiHandler("tabBar")
void onTabSelection(SelectionEvent<Class<Place>> event) {
TabActivity<?, PLACECONTEXT> selectedTabActivity = knownTabs.get(event.getSelectedItem());
if (selectedTabActivity != null) {
GWT.log("Tab selection: " + selectedTabActivity.getPlaceClassForActivation().getName());
if (currentTab != null) {
currentTab.stop();
}
fireEvent(new TabPanelPlaceSelectionEvent(selectedTabActivity));
}
}
/**
* Starts the tab Activity and selects the tab based on the given Place.
*
* @param placeToGo
* the given place.
*/
public void gotoPlace(Place placeToGo) {
if (knownTabs.containsKey(placeToGo.getClass())) {
final TabActivity<Place, PLACECONTEXT> newTabActivity = knownTabs.get(placeToGo.getClass());
newTabActivity.start(placeToGo, tabContentPanelUi);
tabBar.select((Class<Place>) placeToGo.getClass());
currentTab = newTabActivity;
}
}
@Override
protected void onDetach() {
super.onDetach();
Event.setEventListener(back, null);
}
public HandlerRegistration addTabPanelPlaceSelectionEventHandler(TabPanelPlaceSelectionEvent.Handler handler) {
return addHandler(handler, TabPanelPlaceSelectionEvent.TYPE);
}
interface TabPanelUiBinder extends UiBinder<FlowPanel, TabPanel<?>> {
}
}
@@ -0,0 +1,57 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:c="urn:import:com.sap.sse.gwt.client.controls.tabbar">
<ui:style>
.header {
width: 100%;
background-color: #f2f2f2;
position: relative;
}
.headerContent {
width: 100%;
max-width: 80rem;
list-style: none;
margin: 0 auto;
}
.back {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 1em;
background-color: #dedede;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAgCAYAAAAffCjxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4OTE2QjZFRjZCRDkxMUU0ODU5N0U1MEE0MjExRjhEMiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4OTE2QjZGMDZCRDkxMUU0ODU5N0U1MEE0MjExRjhEMiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjg5MTZCNkVENkJEOTExRTQ4NTk3RTUwQTQyMTFGOEQyIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjg5MTZCNkVFNkJEOTExRTQ4NTk3RTUwQTQyMTFGOEQyIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+HQ7CmgAAAOBJREFUeNqs1VEHwzAQB/At3bcre5iyMUpf2m80xp7GpqOv/U77DKPsQkLEJbm73PGnqfoJTe724zjuhHWE3N1zfxAiHWSGNG79NAqIrc1oIJDJKCAXyGoUkMUujAZCgVLINURKUA75xB8bDSQFsREMEiExlEL6EhJCOeRNOWgWamsRD90QZOAgHmqQ9z9uS7DQ5Hbhy8IvyJkLre7eVGH+ry21WHiOqrD4ZIsx7K6JsNTtz2EdB8phM4aVOiQZo/RsEkadIkWMM9dyWMudtCnsIZn9GLZJII+dIF+X4S/AAIE7WYYFvsDQAAAAAElFTkSuQmCC");
background-position: center center;
background-repeat: no-repeat;
background-size: 50%;
-webkit-transition: background-color 0.2s, border-color 0.2s;
transition: background-color 0.2s, border-color 0.2s;
}
.content {
width: 100%;
height: 100%;
}
.tabs {
clear: both;
padding-top: 1rem;
}
</ui:style>
<g:FlowPanel>
<g:HTMLPanel addStyleNames="{style.header}">
<a class="{style.back}" ui:field="back" style="display: none;"></a>
<div class="{style.headerContent}">
<g:SimplePanel ui:field="additionalHeader" />
<c:TabBar ui:field="tabBar" addStyleNames="{style.tabs}" />
</div>
</g:HTMLPanel>
<g:SimplePanel ui:field="tabContentPanelUi"
addStyleNames="{style.content}" />
</g:FlowPanel>
</ui:UiBinder>
@@ -0,0 +1,40 @@
package com.sap.sse.gwt.client.controls.tabbar;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
/**
* Created by pgtaboada on 01.12.14.
*/
public class TabPanelPlaceSelectionEvent<CONTEXT> extends GwtEvent<TabPanelPlaceSelectionEvent.Handler> {
public final static Type<Handler> TYPE = new Type<Handler>();
private TabActivity<?, CONTEXT> selectedActivity;
public TabPanelPlaceSelectionEvent(TabActivity<?, CONTEXT> selectedActivity) {
this.selectedActivity = selectedActivity;
}
@Override
public Type<Handler> getAssociatedType() {
return TYPE;
}
public TabActivity<?, CONTEXT> getSelectedActivity() {
return selectedActivity;
}
@Override
protected void dispatch(Handler handler) {
handler.onTabSelected(this);
}
public interface Handler extends EventHandler {
void onTabSelected(TabPanelPlaceSelectionEvent<?> event);
}
}