/**
 *                                                                            
 *  Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) 
 *                                                                            
 *  All rights reserved. This program and the accompanying materials           
 *  are made available under the terms of the Eclipse Public License 2.0        
 *  which accompanies this distribution, and is available at                  
 *  https://www.eclipse.org/legal/epl-2.0/                                 
 *                                 
 *  SPDX-License-Identifier: EPL-2.0                                 
 *                                                                            
 *  Contributors:                                                      
 * 	   Florian Pirchner - Initial implementation
 * 
 */

package org.eclipse.osbp.ecview.extension.grid.renderer.impl;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.osbp.ecview.core.common.model.binding.BindingFactory;
import org.eclipse.osbp.ecview.core.common.model.binding.YECViewModelValueBindingEndpoint;

import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridButtonRenderer;
import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridRendererClickEvent;
import org.eclipse.osbp.ecview.extension.grid.renderer.CxGridRendererPackage;

/**
 * <!-- begin-user-doc --> An implementation of the model object '
 * <em><b>Cx Grid Button Renderer</b></em>'. <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * </p>
 * <ul>
 *   <li>{@link org.eclipse.osbp.ecview.extension.grid.renderer.impl.CxGridButtonRendererImpl#getNullRepresentation <em>Null Representation</em>}</li>
 *   <li>{@link org.eclipse.osbp.ecview.extension.grid.renderer.impl.CxGridButtonRendererImpl#getLastClickEvent <em>Last Click Event</em>}</li>
 *   <li>{@link org.eclipse.osbp.ecview.extension.grid.renderer.impl.CxGridButtonRendererImpl#getEventTopic <em>Event Topic</em>}</li>
 * </ul>
 *
 * @generated
 */
public class CxGridButtonRendererImpl extends CxGridRendererImpl implements
		CxGridButtonRenderer {
	
	/**
	 * The default value of the '{@link #getNullRepresentation() <em>Null Representation</em>}' attribute.
	 * <!-- begin-user-doc --> <!--
	 * end-user-doc -->
	 * @see #getNullRepresentation()
	 * @generated
	 * @ordered
	 */
	protected static final String NULL_REPRESENTATION_EDEFAULT = "";

	/**
	 * The cached value of the '{@link #getNullRepresentation() <em>Null Representation</em>}' attribute.
	 * <!-- begin-user-doc --> <!--
	 * end-user-doc -->
	 * @see #getNullRepresentation()
	 * @generated
	 * @ordered
	 */
	protected String nullRepresentation = NULL_REPRESENTATION_EDEFAULT;

	/**
	 * The cached value of the '{@link #getLastClickEvent() <em>Last Click Event</em>}' containment reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getLastClickEvent()
	 * @generated
	 * @ordered
	 */
	protected CxGridRendererClickEvent lastClickEvent;

	/**
	 * The default value of the '{@link #getEventTopic() <em>Event Topic</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getEventTopic()
	 * @generated
	 * @ordered
	 */
	protected static final String EVENT_TOPIC_EDEFAULT = "";

	/**
	 * The cached value of the '{@link #getEventTopic() <em>Event Topic</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #getEventTopic()
	 * @generated
	 * @ordered
	 */
	protected String eventTopic = EVENT_TOPIC_EDEFAULT;

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @generated
	 */
	protected CxGridButtonRendererImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @return the e class
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return CxGridRendererPackage.Literals.CX_GRID_BUTTON_RENDERER;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @return the cached value of the '{@link #getNullRepresentation()
	 *         <em>Null Representation</em>}' attribute
	 * @generated
	 */
	public String getNullRepresentation() {
		return nullRepresentation;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param newNullRepresentation
	 *            the new cached value of the '{@link #getNullRepresentation()
	 *            <em>Null Representation</em>}' attribute
	 * @generated
	 */
	public void setNullRepresentation(String newNullRepresentation) {
		String oldNullRepresentation = nullRepresentation;
		nullRepresentation = newNullRepresentation;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__NULL_REPRESENTATION, oldNullRepresentation, nullRepresentation));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @return the cached value of the '{@link #getLastClickEvent()
	 *         <em>Last Click Event</em>}' containment reference
	 * @generated
	 */
	public CxGridRendererClickEvent getLastClickEvent() {
		return lastClickEvent;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param newLastClickEvent
	 *            the new last click event
	 * @param msgs
	 *            the msgs
	 * @return the notification chain
	 * @generated
	 */
	public NotificationChain basicSetLastClickEvent(CxGridRendererClickEvent newLastClickEvent, NotificationChain msgs) {
		CxGridRendererClickEvent oldLastClickEvent = lastClickEvent;
		lastClickEvent = newLastClickEvent;
		if (eNotificationRequired()) {
			ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT, oldLastClickEvent, newLastClickEvent);
			if (msgs == null) msgs = notification; else msgs.add(notification);
		}
		return msgs;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param newLastClickEvent
	 *            the new cached value of the '{@link #getLastClickEvent()
	 *            <em>Last Click Event</em>}' containment reference
	 * @generated
	 */
	public void setLastClickEvent(CxGridRendererClickEvent newLastClickEvent) {
		if (newLastClickEvent != lastClickEvent) {
			NotificationChain msgs = null;
			if (lastClickEvent != null)
				msgs = ((InternalEObject)lastClickEvent).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT, null, msgs);
			if (newLastClickEvent != null)
				msgs = ((InternalEObject)newLastClickEvent).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT, null, msgs);
			msgs = basicSetLastClickEvent(newLastClickEvent, msgs);
			if (msgs != null) msgs.dispatch();
		}
		else if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT, newLastClickEvent, newLastClickEvent));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @return the cached value of the '{@link #getEventTopic()
	 *         <em>Event Topic</em>}' attribute
	 * @generated
	 */
	public String getEventTopic() {
		return eventTopic;
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param newEventTopic
	 *            the new cached value of the '{@link #getEventTopic()
	 *            <em>Event Topic</em>}' attribute
	 * @generated
	 */
	public void setEventTopic(String newEventTopic) {
		String oldEventTopic = eventTopic;
		eventTopic = newEventTopic;
		if (eNotificationRequired())
			eNotify(new ENotificationImpl(this, Notification.SET, CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__EVENT_TOPIC, oldEventTopic, eventTopic));
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @return the YEC view model value binding endpoint
	 */
	public YECViewModelValueBindingEndpoint createLastClickEventEndpoint() {
		YECViewModelValueBindingEndpoint endpoint = BindingFactory.eINSTANCE
				.createYECViewModelValueBindingEndpoint();
		endpoint.setElement(this);
		endpoint.getFeatures()
				.add((EStructuralFeature) CxGridRendererPackage.Literals.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT);
		return endpoint;
	
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param otherEnd
	 *            the other end
	 * @param featureID
	 *            the feature id
	 * @param msgs
	 *            the msgs
	 * @return the notification chain
	 * @generated
	 */
	@Override
	public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
		switch (featureID) {
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT:
				return basicSetLastClickEvent(null, msgs);
		}
		return super.eInverseRemove(otherEnd, featureID, msgs);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param featureID
	 *            the feature id
	 * @param resolve
	 *            the resolve
	 * @param coreType
	 *            the core type
	 * @return the object
	 * @generated
	 */
	@Override
	public Object eGet(int featureID, boolean resolve, boolean coreType) {
		switch (featureID) {
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__NULL_REPRESENTATION:
				return getNullRepresentation();
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT:
				return getLastClickEvent();
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__EVENT_TOPIC:
				return getEventTopic();
		}
		return super.eGet(featureID, resolve, coreType);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param featureID
	 *            the feature id
	 * @param newValue
	 *            the new value
	 * @generated
	 */
	@Override
	public void eSet(int featureID, Object newValue) {
		switch (featureID) {
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__NULL_REPRESENTATION:
				setNullRepresentation((String)newValue);
				return;
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT:
				setLastClickEvent((CxGridRendererClickEvent)newValue);
				return;
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__EVENT_TOPIC:
				setEventTopic((String)newValue);
				return;
		}
		super.eSet(featureID, newValue);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param featureID
	 *            the feature id
	 * @generated
	 */
	@Override
	public void eUnset(int featureID) {
		switch (featureID) {
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__NULL_REPRESENTATION:
				setNullRepresentation(NULL_REPRESENTATION_EDEFAULT);
				return;
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT:
				setLastClickEvent((CxGridRendererClickEvent)null);
				return;
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__EVENT_TOPIC:
				setEventTopic(EVENT_TOPIC_EDEFAULT);
				return;
		}
		super.eUnset(featureID);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @param featureID
	 *            the feature id
	 * @return true, if successful
	 * @generated
	 */
	@Override
	public boolean eIsSet(int featureID) {
		switch (featureID) {
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__NULL_REPRESENTATION:
				return NULL_REPRESENTATION_EDEFAULT == null ? nullRepresentation != null : !NULL_REPRESENTATION_EDEFAULT.equals(nullRepresentation);
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__LAST_CLICK_EVENT:
				return lastClickEvent != null;
			case CxGridRendererPackage.CX_GRID_BUTTON_RENDERER__EVENT_TOPIC:
				return EVENT_TOPIC_EDEFAULT == null ? eventTopic != null : !EVENT_TOPIC_EDEFAULT.equals(eventTopic);
		}
		return super.eIsSet(featureID);
	}

	/**
	 * <!-- begin-user-doc --> <!-- end-user-doc -->.
	 *
	 * @return the string
	 * @generated
	 */
	@Override
	public String toString() {
		if (eIsProxy()) return super.toString();

		StringBuffer result = new StringBuffer(super.toString());
		result.append(" (nullRepresentation: ");
		result.append(nullRepresentation);
		result.append(", eventTopic: ");
		result.append(eventTopic);
		result.append(')');
		return result.toString();
	}

}