Package com.ponysdk.ui.server.basic

Source Code of com.ponysdk.ui.server.basic.PWidget

/*
* Copyright (c) 2011 PonySDK
*  Owners:
*  Luciano Broussal  <luciano.broussal AT gmail.com>
*  Mathieu Barbier   <mathieu.barbier AT gmail.com>
*  Nicolas Ciaravola <nicolas.ciaravola.pro AT gmail.com>
*  WebSite:
*  http://code.google.com/p/pony-sdk/
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.ponysdk.ui.server.basic;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ponysdk.core.UIContext;
import com.ponysdk.core.event.Event;
import com.ponysdk.core.event.EventBus;
import com.ponysdk.core.event.EventHandler;
import com.ponysdk.core.event.HandlerRegistration;
import com.ponysdk.core.event.SimpleEventBus;
import com.ponysdk.core.instruction.AddHandler;
import com.ponysdk.core.instruction.RemoveHandler;
import com.ponysdk.core.instruction.Update;
import com.ponysdk.core.stm.Txn;
import com.ponysdk.core.tools.Objects;
import com.ponysdk.ui.server.basic.event.HasPWidgets;
import com.ponysdk.ui.server.basic.event.PBlurEvent;
import com.ponysdk.ui.server.basic.event.PClickEvent;
import com.ponysdk.ui.server.basic.event.PContextMenuEvent;
import com.ponysdk.ui.server.basic.event.PDomEvent;
import com.ponysdk.ui.server.basic.event.PDoubleClickEvent;
import com.ponysdk.ui.server.basic.event.PDragEndEvent;
import com.ponysdk.ui.server.basic.event.PDragEnterEvent;
import com.ponysdk.ui.server.basic.event.PDragLeaveEvent;
import com.ponysdk.ui.server.basic.event.PDragOverEvent;
import com.ponysdk.ui.server.basic.event.PDragStartEvent;
import com.ponysdk.ui.server.basic.event.PDropEvent;
import com.ponysdk.ui.server.basic.event.PFocusEvent;
import com.ponysdk.ui.server.basic.event.PKeyPressEvent;
import com.ponysdk.ui.server.basic.event.PKeyUpEvent;
import com.ponysdk.ui.server.basic.event.PMouseDownEvent;
import com.ponysdk.ui.server.basic.event.PMouseEvent;
import com.ponysdk.ui.server.basic.event.PMouseOutEvent;
import com.ponysdk.ui.server.basic.event.PMouseOverEvent;
import com.ponysdk.ui.server.basic.event.PMouseUpEvent;
import com.ponysdk.ui.terminal.Dictionnary.HANDLER;
import com.ponysdk.ui.terminal.Dictionnary.PROPERTY;
import com.ponysdk.ui.terminal.DomHandlerType;

/**
* The base class for the majority of user-interface objects. Widget adds support for receiving events from
* the browser and being added directly to {@link PPanel panels}.
*/
public abstract class PWidget extends PObject implements IsPWidget {

    private static Logger log = LoggerFactory.getLogger(PWidget.class);

    protected PWidget parent;

    protected Object data;

    private Set<String> styleNames;
    private Set<PEvent> preventEvents;
    private Set<PEvent> stopEvents;

    private EventBus domHandler;

    private Map<String, String> styleProperties;
    private Map<String, String> elementProperties;
    private Map<String, String> elementAttributes;

    protected boolean visible = true;
    private String title;
    private String width;
    private String height;
    private String styleName;
    private String stylePrimaryName;
    private String debugID;

    public static PWidget asWidgetOrNull(final IsPWidget w) {
        return w == null ? null : w.asWidget();
    }

    private final Set<String> safeStyleName() {
        if (styleNames != null) return styleNames;
        styleNames = new HashSet<String>();
        return styleNames;
    }

    private final Set<PEvent> safePreventEvents() {
        if (preventEvents != null) return preventEvents;
        preventEvents = new HashSet<PEvent>();
        return preventEvents;
    }

    private final Set<PEvent> safeStopEvents() {
        if (stopEvents != null) return stopEvents;
        stopEvents = new HashSet<PEvent>();
        return stopEvents;
    }

    private final Map<String, String> safeStyleProperties() {
        if (styleProperties != null) return styleProperties;
        styleProperties = new HashMap<String, String>();
        return styleProperties;
    }

    private final Map<String, String> safeElementProperties() {
        if (elementProperties != null) return elementProperties;
        elementProperties = new HashMap<String, String>();
        return elementProperties;
    }

    private final Map<String, String> safeElementAttributes() {
        if (elementAttributes != null) return elementAttributes;
        elementAttributes = new HashMap<String, String>();
        return elementAttributes;
    }

    public void setVisible(final boolean visible) {
        if (Objects.equals(this.visible, visible)) return;
        this.visible = visible;
        saveUpdate(PROPERTY.WIDGET_VISIBLE, visible);
    }

    public void setWidth(final String width) {
        if (Objects.equals(this.width, width)) return;
        this.width = width;
        saveUpdate(PROPERTY.WIDGET_WIDTH, width);
    }

    public void setHeight(final String height) {
        if (Objects.equals(this.height, height)) return;
        this.height = height;
        saveUpdate(PROPERTY.WIDGET_HEIGHT, height);
    }

    public void setTitle(final String title) {
        if (Objects.equals(this.title, title)) return;
        this.title = title;
        saveUpdate(PROPERTY.WIDGET_TITLE, title);
    }

    public void setStyleName(final String styleName) {
        if (Objects.equals(this.styleName, styleName)) return;
        this.styleName = styleName;
        saveUpdate(PROPERTY.STYLE_NAME, styleName);
    }

    public void setStylePrimaryName(final String stylePrimaryName) {
        if (Objects.equals(this.stylePrimaryName, stylePrimaryName)) return;
        this.stylePrimaryName = stylePrimaryName;
        saveUpdate(PROPERTY.STYLE_PRIMARY_NAME, stylePrimaryName);
    }

    public void ensureDebugId(final String debugID) {
        if (Objects.equals(this.debugID, debugID)) return;
        this.debugID = debugID;
        saveUpdate(PROPERTY.ENSURE_DEBUG_ID, debugID);
    }

    public String getTitle() {
        return title;
    }

    public boolean isVisible() {
        return visible;
    }

    public String getWidth() {
        return width;
    }

    public String getHeight() {
        return height;
    }

    public String getStyleName() {
        return styleName;
    }

    public String getDebugID() {
        return debugID;
    }

    public String getStylePrimaryName() {
        return stylePrimaryName;
    }

    public PWidget getParent() {
        return parent;
    }

    public void setParent(final PWidget parent) {
        this.parent = parent;
    }

    public void setStyleProperty(final String name, final String value) {
        final String previous = safeStyleProperties().put(name, value);
        if (!Objects.equals(previous, value)) {
            final Update update = new Update(ID);
            update.put(PROPERTY.PUT_STYLE_KEY, name);
            update.put(PROPERTY.STYLE_VALUE, value);
            Txn.get().getTxnContext().save(update);
        }
    }

    public void removeStyleProperty(final String name) {
        final String previous = safeStyleProperties().remove(name);
        if (previous != null) {
            final Update update = new Update(ID);
            update.put(PROPERTY.REMOVE_STYLE_KEY, name);
            Txn.get().getTxnContext().save(update);
        }
    }

    public void setProperty(final String name, final String value) {
        final String previous = safeElementProperties().put(name, value);
        if (!Objects.equals(previous, value)) {
            final Update update = new Update(ID);
            update.put(PROPERTY.PUT_PROPERTY_KEY, name);
            update.put(PROPERTY.PROPERTY_VALUE, value);
            Txn.get().getTxnContext().save(update);
        }
    }

    public void setAttribute(final String name, final String value) {
        final String previous = safeElementAttributes().put(name, value);
        if (!Objects.equals(previous, value)) {
            final Update update = new Update(ID);
            update.put(PROPERTY.PUT_ATTRIBUTE_KEY, name);
            update.put(PROPERTY.ATTRIBUTE_VALUE, value);
            Txn.get().getTxnContext().save(update);
        }
    }

    public void removeAttribute(final String name) {
        final String previous = safeElementAttributes().remove(name);
        if (previous != null) {
            final Update update = new Update(ID);
            update.put(PROPERTY.REMOVE_ATTRIBUTE_KEY, name);
            Txn.get().getTxnContext().save(update);
        }
    }

    public String getProperty(final String key) {
        if (elementProperties == null) return null;
        return elementProperties.get(key);
    }

    public String getAttribute(final String key) {
        if (elementAttributes == null) return null;
        return elementAttributes.get(key);
    }

    public void preventEvent(final PEvent e) {
        if (safePreventEvents().add(e)) {
            final Update update = new Update(ID);
            update.put(PROPERTY.PREVENT_EVENT, e.getCode());
            Txn.get().getTxnContext().save(update);
        }
    }

    public void stopEvent(final PEvent e) {
        if (safeStopEvents().add(e)) {
            final Update update = new Update(ID);
            update.put(PROPERTY.STOP_EVENT, e.getCode());
            Txn.get().getTxnContext().save(update);
        }
    }

    public void addStyleName(final String styleName) {
        if (safeStyleName().add(styleName)) {
            final Update update = new Update(ID);
            update.put(PROPERTY.ADD_STYLE_NAME, styleName);
            Txn.get().getTxnContext().save(update);
        }
    }

    public void removeStyleName(final String styleName) {
        if (styleNames == null) return;
        if (styleNames.remove(styleName)) {
            removeStyle(styleName);
        }
    }

    private void removeStyle(final String styleName) {
        final Update update = new Update(ID);
        update.put(PROPERTY.REMOVE_STYLE_NAME, styleName);
        Txn.get().getTxnContext().save(update);
    }

    public boolean hasStyleName(final String styleName) {
        if (styleNames == null) return false;
        return styleNames.contains(styleName);
    }

    public Object getData() {
        return data;
    }

    public void setData(final Object data) {
        this.data = data;
    }

    public void setDomHandler(final EventBus domHandler) {
        this.domHandler = domHandler;
    }

    @Override
    public PWidget asWidget() {
        return this;
    }

    public void setSizeFull() {
        setWidth(Size.HUNDRED_PERCENT);
        setHeight(Size.HUNDRED_PERCENT);
    }

    public <H extends EventHandler> HandlerRegistration removeDomHandler(final H handler, final PDomEvent.Type<H> type) {
        final HandlerRegistration handlerRegistration = ensureDomHandler().addHandler(type, handler);
        final RemoveHandler removeHandler = new RemoveHandler(getID(), HANDLER.KEY_.DOM_HANDLER);
        if (handler instanceof JSONObject) {
            removeHandler.put(PROPERTY.DOM_HANDLER_CODE, handler);
        }
        Txn.get().getTxnContext().save(removeHandler);
        return handlerRegistration;
    }

    @SuppressWarnings("unchecked")
    public <H extends EventHandler> HandlerRegistration addDomHandler(final H handler, final PDomEvent.Type<H> type) {
        final Set<H> handlerSet = ensureDomHandler().getHandlerSet(type, this);
        final HandlerRegistration handlerRegistration = domHandler.addHandlerToSource(type, this, handler);
        if (handlerSet.isEmpty()) {
            final AddHandler addHandler = new AddHandler(getID(), HANDLER.KEY_.DOM_HANDLER);
            addHandler.put(PROPERTY.DOM_HANDLER_CODE, type.getDomHandlerType().ordinal());
            if (handler instanceof JSONObject) {
                try {
                    final JSONObject jso = (JSONObject) handler;
                    for (final Iterator<String> iterator = jso.keys(); iterator.hasNext();) {
                        final String key = iterator.next();
                        addHandler.put(key, jso.get(key));
                    }
                } catch (final JSONException e) {
                    log.error("Failed to copy value", e);
                }
            }
            Txn.get().getTxnContext().save(addHandler);
        }
        return handlerRegistration;
    }

    @Override
    public void onClientData(final JSONObject instruction) throws JSONException {
        if (instruction.has(HANDLER.KEY) && instruction.getString(HANDLER.KEY).equals(HANDLER.KEY_.DOM_HANDLER)) {
            final DomHandlerType domHandler = DomHandlerType.values()[instruction.getInt(PROPERTY.DOM_HANDLER_TYPE)];
            switch (domHandler) {
                case KEY_PRESS:
                    fireEvent(new PKeyPressEvent(this, instruction.getInt(PROPERTY.VALUE)));
                    break;
                case KEY_UP:
                    fireEvent(new PKeyUpEvent(this, instruction.getInt(PROPERTY.VALUE)));
                    break;
                case CLICK:
                    fireMouseEvent(instruction, new PClickEvent(this));
                    break;
                case DOUBLE_CLICK:
                    fireMouseEvent(instruction, new PDoubleClickEvent(this));
                    break;
                case MOUSE_OVER:
                    fireMouseEvent(instruction, new PMouseOverEvent(this));
                    break;
                case MOUSE_OUT:
                    fireMouseEvent(instruction, new PMouseOutEvent(this));
                    break;
                case MOUSE_DOWN:
                    fireMouseEvent(instruction, new PMouseDownEvent(this));
                    break;
                case MOUSE_UP:
                    fireMouseEvent(instruction, new PMouseUpEvent(this));
                    break;
                case FOCUS:
                    fireEvent(new PFocusEvent(this));
                    break;
                case BLUR:
                    fireEvent(new PBlurEvent(this));
                    break;
                case DRAG_START:
                    fireEvent(new PDragStartEvent(this));
                    break;
                case DRAG_END:
                    fireEvent(new PDragEndEvent(this));
                    break;
                case DRAG_ENTER:
                    fireEvent(new PDragEnterEvent(this));
                    break;
                case DRAG_LEAVE:
                    fireEvent(new PDragLeaveEvent(this));
                    break;
                case DRAG_OVER:
                    fireEvent(new PDragOverEvent(this));
                    break;
                case DROP:
                    final PDropEvent dropEvent = new PDropEvent(this);
                    if (instruction.has(PROPERTY.DRAG_SRC)) {
                        final PWidget source = UIContext.get().getObject(instruction.getLong(PROPERTY.DRAG_SRC));
                        dropEvent.setDragSource(source);
                    }
                    fireEvent(dropEvent);
                    break;
                case CONTEXT_MENU:
                    fireEvent(new PContextMenuEvent(this));
                    break;
                default:
                    log.error("Dom Handler not implemented: " + domHandler);
                    break;
            }
        } else {
            super.onClientData(instruction);
        }
    }

    private EventBus ensureDomHandler() {
        if (domHandler == null) domHandler = new SimpleEventBus();
        return domHandler;
    }

    protected <H extends EventHandler> Set<H> getHandlerSet(final PDomEvent.Type<H> type, final Object source) {
        return ensureDomHandler().getHandlerSet(type, null);
    }

    public void fireMouseEvent(final JSONObject instruction, final PMouseEvent<?> event) throws JSONException {
        event.setX(instruction.getInt(PROPERTY.X));
        event.setY(instruction.getInt(PROPERTY.Y));
        event.setNativeButton(instruction.getInt(PROPERTY.NATIVE_BUTTON));
        event.setClientX(instruction.getInt(PROPERTY.CLIENT_X));
        event.setClientY(instruction.getInt(PROPERTY.CLIENT_Y));
        event.setSourceAbsoluteLeft((int) instruction.getDouble(PROPERTY.SOURCE_ABSOLUTE_LEFT));
        event.setSourceAbsoluteTop((int) instruction.getDouble(PROPERTY.SOURCE_ABSOLUTE_TOP));
        event.setSourceOffsetHeight((int) instruction.getDouble(PROPERTY.SOURCE_OFFSET_HEIGHT));
        event.setSourceOffsetWidth((int) instruction.getDouble(PROPERTY.SOURCE_OFFSET_WIDTH));

        fireEvent(event);
    }

    public void fireEvent(final Event<?> event) {
        if (domHandler == null) return;
        domHandler.fireEvent(event);
    }

    public void removeFromParent() {
        if (parent instanceof HasPWidgets) {
            ((HasPWidgets) parent).remove(this);
        } else if (parent != null) { throw new IllegalStateException("This widget's parent does not implement HasPWidgets"); }
    }

    protected void saveUpdate(final String key, final boolean value) {
        final Update update = new Update(getID());
        update.put(key, value);
        Txn.get().getTxnContext().save(update);
    }

    protected void saveUpdate(final String key, final int value) {
        final Update update = new Update(getID());
        update.put(key, value);
        Txn.get().getTxnContext().save(update);
    }

    protected void saveUpdate(final String key, final Object value) {
        final Update update = new Update(getID());
        update.put(key, value);
        Txn.get().getTxnContext().save(update);
    }

}
TOP

Related Classes of com.ponysdk.ui.server.basic.PWidget

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.