/* * * Copyright (C) 2007-2013 Licensed to the Comunes Association (CA) under * one or more contributor license agreements (see COPYRIGHT for details). * The CA licenses this file to you under the GNU Affero General Public * License version 3, (the "License"); you may not use this file except in * compliance with the License. This file is part of kune. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package cc.kune.gspace.client.armor; import static cc.kune.polymer.client.Layout.*; import static cc.kune.polymer.client.PolymerId.*; import java.util.HashMap; import com.google.gwt.dom.client.BodyElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.i18n.client.HasDirection.Direction; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.ButtonBase; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.InsertPanel.ForIsWidget; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import br.com.rpa.client._paperelements.PaperButton; import cc.kune.common.client.actions.ui.ActionFlowPanel; import cc.kune.common.client.actions.ui.IsActionExtensible; import cc.kune.common.client.errors.UIException; import cc.kune.common.client.log.Log; import cc.kune.common.client.ui.HTMLId; import cc.kune.common.client.ui.WrappedFlowPanel; import cc.kune.polymer.client.PolymerUtils; @Singleton public class GSpaceArmorPolymer implements GSpaceArmor { private static Element getElementById(final String id) { return DOM.getElementById(id); } private native static Element getShadowElement(String father, String child) /*-{ return $doc.querySelector(father).shadowRoot.querySelector(child) }-*/; private static boolean isElementChildOfWidget(Element element) { // Walk up the DOM hierarchy, looking for any widget with an event listener // set. Though it is not dependable in the general case that a widget will // have set its element's event listener at all times, it *is* dependable // if the widget is attached. Which it will be in this case. element = element.getParentElement(); final BodyElement body = Document.get().getBody(); while ((element != null) && (body != element)) { if (Event.getEventListener(element) != null) { Log.error("Element: " + element + " already wrapped/attached"); return true; } element = element.getParentElement().cast(); } return false; } private final GSpaceCenter centerPanel; private final ActionFlowPanel docFooterActionsToolbar; private final ActionFlowPanel docHeaderRightActionsToolbar; private final ActionFlowPanel docTopActionsToolbar; private final HashMap<String, Element> elements; private final ActionFlowPanel entityFooterActionsToolbar; private final ActionFlowPanel headerActionsTopToolbar; private final HashMap<String, WrappedFlowPanel> panels; @Inject public GSpaceArmorPolymer(final GSpaceCenter centerPanel, final Provider<ActionFlowPanel> toolbarProv) { panels = new HashMap<String, WrappedFlowPanel>(); elements = new HashMap<String, Element>(); docHeaderRightActionsToolbar = toolbarProv.get(); docFooterActionsToolbar = toolbarProv.get(); headerActionsTopToolbar = toolbarProv.get(); docTopActionsToolbar = toolbarProv.get(); entityFooterActionsToolbar = toolbarProv.get(); docHeaderRightActionsToolbar.addStyleName("btn-group"); docTopActionsToolbar.addStyleName("btn-group"); PolymerUtils.addLayout(entityFooterActionsToolbar, HORIZONTAL, LAYOUT, START_JUSTIFIED); PolymerUtils.addLayout(headerActionsTopToolbar, HORIZONTAL, LAYOUT, END_JUSTIFIED); getEntityHeader().add(headerActionsTopToolbar); getDocFooter().add(docFooterActionsToolbar); getEntityFooter().add(entityFooterActionsToolbar); getDocHeaderRight().add(docHeaderRightActionsToolbar); getDocTopbar().add(docTopActionsToolbar); this.centerPanel = centerPanel; wrapDiv(DOC_CONTENT).add(centerPanel); } @Override public void clearBackImage() { setBackImage("none !important"); } @Override public void enableCenterScroll(final boolean enable) { try { /* * NOTE: With Overflow.SCROLL instead of VISIBLE, breaks header and wave * navegation */ getElementById("doc_content_section").getStyle().setOverflowY( enable ? Overflow.VISIBLE : Overflow.HIDDEN); } catch (final Exception e) { Log.error("Cannot set scroll in center panel"); } } @Override public GSpaceCenter getDocContainer() { return centerPanel; } @Override public int getDocContainerHeight() { return wrapDiv(DOC_CONTENT).getElement().getOffsetHeight(); } @Override public ForIsWidget getDocFooter() { return wrapDiv(MIGA); } @Override public IsActionExtensible getDocFooterActionsToolbar() { return docFooterActionsToolbar; } @Override public ForIsWidget getDocHeader() { return wrapDiv(DOC_HEADER_LEFT_EXTENSIONBAR); } private WrappedFlowPanel getDocHeaderRight() { return wrapDiv(DOC_HEADER_RIGHT_EXTENSIONBAR); } @Override public IsActionExtensible getDocHeaderRightActionsToolbar() { return docHeaderRightActionsToolbar; } @Override public ActionFlowPanel getDocTopActionsToolbar() { return docTopActionsToolbar; } @Override public ForIsWidget getDocTopbar() { return wrapDiv(DOC_TOOLBAR_EXTENSION); } @Override public Element getElement(final HTMLId htmlId) { final String id = htmlId.getId(); Element element = elements.get(id); if (element == null) { element = getElementById(id); elements.put(id, element); } return element; } @Override public ForIsWidget getEntityFooter() { return wrapDiv(GROUP_BOTTOMBAR); } @Override public ForIsWidget getEntityHeader() { return wrapDiv(GROUP_ENTITY_TOOLBAR); } @Override public ForIsWidget getEntityToolsCenter() { return wrapDiv(GROUP_TOOLS_TOOLBAR); } @Override public ForIsWidget getEntityToolsNorth() { return wrapDiv(HEADER_SOCIAL_NET); } @Override public ButtonBase getFollowersButton() { return PaperButton.wrap(GROUP_FOLLOWERS.getId()); } @Override public Image getGroupLogo() { return Image.wrap(getElement(HEADER_GROUP_LOGO)); } @Override public WrappedFlowPanel getGroupName() { return wrapDiv(HEADER_GROUP_NAME); } @Override public WrappedFlowPanel getGroupShortName() { return wrapDiv(HEADER_SHORT_GROUP_NAME); } @Override public IsActionExtensible getHeaderActionsTopToolbar() { return headerActionsTopToolbar; } @Override public ForIsWidget getHeaderBottombar() { return wrapDiv(HEADER_BOTTOMBAR); } public ForIsWidget getHomeSpaceFlow() { return wrapDiv(HOME_CENTER); } @Override public Element getLogoShadow() { return getElement(HEADER_GROUP_SHADOW); } @Override public ForIsWidget getSitebarLeft() { return wrapDiv(SITEBAR_LEFT_EXTENSIONBAR); } @Override public ForIsWidget getSitebarRight() { return wrapDiv(SITEBAR_RIGHT_EXTENSIONBAR); } private void getSpace(final int index) { getElement(SPACE_SELECTOR).setPropertyInt("selected", index); } @Override public IsActionExtensible getTopActionsToolbar() { return docTopActionsToolbar; } @Override public ForIsWidget getUserSpace() { return wrapDiv(USER_SPACE_CONTENT); } @Override public void selectGroupSpace() { getSpace(2); } @Override public void selectHomeSpace() { getSpace(0); } @Override public void selectPublicSpace() { getSpace(2); } @Override public void selectUserSpace() { getSpace(1); } @Override public void setBackImage(final String url) { PolymerUtils.setBackImage(url); } @Override public void setRTL(final Direction direction) { // TODO use reverse methods in Polymer also // http://stackoverflow.com/questions/26110405/polymer-rtl-text-based-on-an-attribute } @Override public WrappedFlowPanel wrapDiv(final HTMLId htmlId) { final String id = htmlId.getId(); Log.debug("Wrapping id: " + id); WrappedFlowPanel panel = panels.get(id); if (panel == null) { Log.debug("Getting div '" + id + "' from html"); final Element element = getElement(htmlId); if (element == null) { // Not found, return null as getElementById Log.warn("Cannot find html element with id: " + id); return null; } if (isElementChildOfWidget(element)) { throw new UIException("Parent is already wrapped/attached"); } panel = WrappedFlowPanel.wrap(element); if (panel == null) { Log.error("Error wrapping html element with id: " + id); } assert panel != null; panels.put(id, panel); } return panel; } }