text:
#include <xip/system/standard.h>
#include <xip/system/GL/gl.h>

#include "SoXipFbo.h"
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/errors/SoDebugError.h>
#include <Inventor/elements/SoViewportRegionElement.h>
#include <Inventor/elements/SoGLTextureEnabledElement.h>
#include <xip/inventor/core/SoXipMultiTextureElement.h>
#include <xip/inventor/coregl/SoXipDrawBuffersElement.h>
#include <xip/inventor/coregl/SoXipFboElement.h>

const GLenum SoXipFbo::avaliableColorTargets[16] =
        { GL_COLOR_ATTACHMENT0_EXT,  GL_COLOR_ATTACHMENT1_EXT,
          GL_COLOR_ATTACHMENT2_EXT,  GL_COLOR_ATTACHMENT3_EXT,
          GL_COLOR_ATTACHMENT4_EXT,  GL_COLOR_ATTACHMENT5_EXT,
          GL_COLOR_ATTACHMENT6_EXT,  GL_COLOR_ATTACHMENT7_EXT,
          GL_COLOR_ATTACHMENT8_EXT,  GL_COLOR_ATTACHMENT9_EXT,
          GL_COLOR_ATTACHMENT10_EXT, GL_COLOR_ATTACHMENT11_EXT,
          GL_COLOR_ATTACHMENT12_EXT, GL_COLOR_ATTACHMENT13_EXT,
          GL_COLOR_ATTACHMENT14_EXT, GL_COLOR_ATTACHMENT15_EXT };

SO_NODE_SOURCE(SoXipFbo);

SoXipFbo::SoXipFbo() {
	SO_NODE_CONSTRUCTOR(SoXipFbo);

	SO_NODE_ADD_FIELD(width, (0));
	SO_NODE_ADD_FIELD(height, (0));
	SO_NODE_ADD_FIELD(autoSize,  (false));

	SO_NODE_ADD_FIELD(colorAttachments, (0));
	SO_NODE_ADD_FIELD(colorFormat, (RGBA));
	SO_NODE_ADD_FIELD(colorInternal, (RGBA8));

    SO_NODE_ADD_FIELD(useDepthBuffer, (true));

    SO_NODE_ADD_FIELD(colorHandlesOutput, (0));
    //SO_NODE_ADD_FIELD(outFboSetup, (0));

	SO_NODE_DEFINE_ENUM_VALUE(Format, ALPHA);
	SO_NODE_DEFINE_ENUM_VALUE(Format, LUMINANCE);
	SO_NODE_DEFINE_ENUM_VALUE(Format, LUMINANCE_ALPHA);
	SO_NODE_DEFINE_ENUM_VALUE(Format, INTENSITY);
	SO_NODE_DEFINE_ENUM_VALUE(Format, RGB);
	SO_NODE_DEFINE_ENUM_VALUE(Format, RGBA);
	SO_NODE_SET_SF_ENUM_TYPE(colorFormat, Format);

	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, ALPHA4);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, ALPHA8);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, ALPHA12);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, ALPHA16);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, ALPHA16F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, ALPHA32F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE4);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE8);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE12);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE16);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE16F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE32F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE4_ALPHA4);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE6_ALPHA2);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE8_ALPHA8);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE12_ALPHA4);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE12_ALPHA12);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE16_ALPHA16);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE_ALPHA16F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, LUMINANCE_ALPHA32F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, INTENSITY4);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, INTENSITY8);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, INTENSITY12);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, INTENSITY16);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, INTENSITY16F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, INTENSITY32F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, R3_G3_B2);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB4);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB5);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB8);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB10);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB12);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB16);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB16F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB32F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGBA2);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGBA4);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB5_A1);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGBA8);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGB10_A2);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGBA12);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGBA16);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGBA16F_ARB);
	SO_NODE_DEFINE_ENUM_VALUE(InternalColorFormat, RGBA32F_ARB);
	SO_NODE_SET_SF_ENUM_TYPE(colorInternal, InternalColorFormat);

    SoField* fields[] = { &colorFormat, &colorInternal, &useDepthBuffer };
	SoField* fieldsOut[] = { &colorHandlesOutput };

    // Attach input sensor to input fields
	mNumFields = sizeof(fields) / sizeof(fields[0]);
	mSensors = new SoFieldSensor*[mNumFields];
	for (int i = 0; i < mNumFields; i++) {
		mSensors[i] = new SoFieldSensor(sensorCB, this);
		mSensors[i]->attach(fields[i]);
	}

    // Attach output sensor to output fields
	mNumFieldsOut = sizeof(fieldsOut) / sizeof(fieldsOut[0]);
	mSensorsOut = new SoFieldSensor*[mNumFieldsOut];
	for (int i = 0; i < mNumFieldsOut; i++) {
		mSensorsOut[i] = new SoFieldSensor(sensorOutCB, this);
		mSensorsOut[i]->attach(fieldsOut[i]);
	}

    mColorAttachmentsSensor = new SoFieldSensor(sensorCB, this);
    mColorAttachmentsSensor->attach(&colorAttachments);

    mNumColorHandles = 0;
    for (int i = 0; i < 16; i++)
        mColorHandles[i] = 0;
    mDepthHandle = 0;

    mMaxBuffers = 0;
    mErrorInSetup = false;
	mNeedsUpdate = true;
	mIsAllocated = false;
    mIsColorsAllocated = false;
    mIsDepthAllocated = false;

    mDefaultWrap = GL_CLAMP;
    mDefaultFilter = GL_LINEAR;
    mDefaultDepthFormat = GL_DEPTH_COMPONENT24;
}

/**
 *  Destructor.
 */
SoXipFbo::~SoXipFbo() {
	for (int i = 0; i < mNumFields; i++) {
		delete mSensors[i];
	}
	delete [] mSensors;

	for (int i = 0; i < mNumFieldsOut; i++) {
		delete mSensorsOut[i];
	}
	delete [] mSensorsOut;

	if (mIsAllocated)
		deallocate();

    delete mColorAttachmentsSensor;
}

/**
 *  Class initiator.
 */
void SoXipFbo::initClass() {
	SO_NODE_INIT_CLASS(SoXipFbo, SoGroup, "SoGroup");

	SO_ENABLE(SoGLRenderAction, SoXipGLOWElement);
	SO_ENABLE(SoGLRenderAction, SoXipFboElement);
    SO_ENABLE(SoGLRenderAction, SoXipDrawBuffersElement);
}

/**
 *  Run a check and output any errors.
 */
bool SoXipFbo::checkFramebufferStatus() {
    bool isOk = false;
    GLenum status = (GLenum)glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    switch(status) {
        case GL_FRAMEBUFFER_COMPLETE_EXT:
            isOk = true;
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT");
            break;
        case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_UNSUPPORTED_EXT");
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT");
            SoDebugError::post("SoXipFbo", "The fbo will be incomplete without color attachments");
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT");
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT");
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT");
            if (!mFboOut.numColorAttachments)
                SoDebugError::post("SoXipFbo", "The fbo will be incomplete without color attachments");
            SoDebugError::post("SoXipFbo", "One or more render targets have no attached buffer(s)");
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT");
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT");
            if (useDepthBuffer.getValue())
                SoDebugError::post("SoXipFbo", "Try turning the depth buffer off or replace with 3D depth");
            break;
        case GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT");
            break;
        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT:
            SoDebugError::post("SoXipFbo", "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT");
            break;
        default:
            SoDebugError::post("SoXipFbo", "UNKNOWN frambuffer error %i", status);
    }

    return isOk;
}

/**
 *  Clamp attachment number field between 0 and context maximum.
 *  Max is extracted from context via glGet with GL_MAX_COLOR_ATTACHMENTS
 */
void SoXipFbo::checkMaxNumBuffers()
{
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &mMaxBuffers);

    int val = colorAttachments.getValue();
    int max = mMaxBuffers;
    if (val < 0 || val > max) {
        val = (val < 0) ? 0 : (val > max) ? max : val;
        colorAttachments.setValue(val);
        SoDebugError::postInfo("SoXipDBO", "Valid range of attachments are [0,%d]", max);
    }
}

/**
 *  Allocates and sets up the Fbo.
 *  @see allocateInternalColors()
 *  @see allocateInternalDepth()
 */
void SoXipFbo::allocateFbo()
{
    glGenFramebuffersEXT(1, &mFboIn.fboHandle);
    mIsAllocated = true;
    mFboIn.width = width.getValue();
    mFboIn.height = height.getValue();
    mFboIn.numColorAttachments = colorAttachments.getValue();
    mFboIn.numDepthAttachments = (useDepthBuffer.getValue()) ? 1 : 0;
    mFboIn.colorStorage = GL_TEXTURE_2D;
    mFboIn.depthStorage = GL_RENDERBUFFER_EXT;
    mFboIn.internalColorFormat = colorInternal.getValue();
    mFboIn.internalDepthFormat = GL_DEPTH_COMPONENT24;
    mFboIn.colorFormat = colorFormat.getValue();
    mFboIn.colorWrap = GL_CLAMP;
    mFboIn.colorFilter = GL_LINEAR;
    mFboIn.hasModColors = false;
    mFboIn.hasModDepth = false;
    mFboIn.isComplete = false;
    mFboIn.isDirty = true;
}

/**
 *  Creates color attachment(s).
 *  Allocates only, the binding/attaching takes place in elsewhere.
 *  @see allocateInternalDepth()
 *  @see allocateFbo()
 */
void SoXipFbo::allocateInternalColors()
{
    if (mFboOut.numColorAttachments)
    {
        glGenTextures(mFboOut.numColorAttachments, mFboOut.colorHandles);
        //SoDebugError::postInfo("SoXipFbo", "Allocated internal colors");
    }

    for (unsigned int i = mFboOut.numColorAttachments; i < 16; i++)
        mFboOut.colorHandles[i] = 0;

    for (unsigned int i = 0; i < mFboOut.numColorAttachments; i++)
    {
        glBindTexture(GL_TEXTURE_2D, mFboOut.colorHandles[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mFboOut.colorWrap);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mFboOut.colorWrap);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mFboOut.colorFilter);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mFboOut.colorFilter);
        glTexImage2D(GL_TEXTURE_2D, 0, mFboOut.internalColorFormat, mFboOut.width, mFboOut.height,
            0, mFboOut.colorFormat, GL_UNSIGNED_BYTE, NULL);
    }
	glBindTexture(GL_TEXTURE_2D, 0);

    for (int i = 0; i < 16; i++)
        mColorHandles[i] = mFboOut.colorHandles[i];

    mNumColorHandles = mFboOut.numColorAttachments;
    mIsColorsAllocated = true;
}

/**
 *  Creates depth attachment.
 *  Allocates only, the binding/attaching takes place elsewhere.
 *  @see allocateInternalColors()
 *  @see allocateFbo()
 */
void SoXipFbo::allocateInternalDepth()
{
    if (mFboOut.numDepthAttachments)
    {
        glGenRenderbuffersEXT(mFboOut.numDepthAttachments, &mFboOut.depthHandle);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mFboOut.depthHandle);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, mFboOut.internalDepthFormat, mFboOut.width, mFboOut.height);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
        //SoDebugError::postInfo("SoXipFbo", "Allocated internal depth");
    }
    else
        mFboOut.depthHandle = 0;

    mDepthHandle = mFboOut.depthHandle;
    mIsDepthAllocated = true;
}

/**
 *  Deallocation of a internal color buffers.
 */
void SoXipFbo::deallocateInternalColors()
{
    if (mNumColorHandles)
    {
        glDeleteTextures(mNumColorHandles, mColorHandles);
        //SoDebugError::postInfo("SoXipFbo", "Deallocated internal colors");
    }

    for (int i = 0; i < 16; i++)
		mColorHandles[i] = 0;
    mNumColorHandles = 0;
    mIsColorsAllocated = false;
}

/**
 *  Deallocation of internal depth buffer.
 */
void SoXipFbo::deallocateInternalDepth()
{
    if (mDepthHandle)
    {
        glDeleteRenderbuffersEXT(1, &mDepthHandle);
        //SoDebugError::postInfo("SoXipFbo", "Deallocated internal depth");
    }

    mDepthHandle = 0;
    mIsDepthAllocated = false;
}

/**
 *  Full deallocation.
 */
void SoXipFbo::deallocate()
{
	glDeleteFramebuffersEXT(1, &mFboOut.fboHandle);
    if (mIsColorsAllocated)
        deallocateInternalColors();
    if (mIsDepthAllocated)
        deallocateInternalDepth();

    mFboOut.fboHandle = 0;
    mNumColorHandles = 0;
    for (int i = 0; i < 16; i++)
		mColorHandles[i] = 0;
    mDepthHandle = 0;

    mIsColorsAllocated = false;
    mIsDepthAllocated = false;
	mIsAllocated = false;
}

/**
 *  AttachColors.
 */
void SoXipFbo::attachColors()
{
    // Attach colors
    if (mFboOut.colorStorage == GL_TEXTURE_2D)
    {
        for (unsigned int i = 0; i < mFboOut.numColorAttachments; i++)
            glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_TEXTURE_2D, mFboOut.colorHandles[i], 0);
        for (unsigned int i = mFboOut.numColorAttachments; i < (unsigned int)mMaxBuffers; i++)
            glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_TEXTURE_2D, 0, 0);
        //SoDebugError::postInfo("SoXipFbo", "Attaching 2D color targets %d %d", mFboOut.colorHandles[0], mFboOut.colorHandles[1]);
    }
    else if (mFboOut.colorStorage == GL_TEXTURE_3D)
    {
        for (unsigned int i = 0; i < mFboOut.numColorAttachments; i++)
            glFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, mFboOut.colorHandles[i], 0);
        for (unsigned int i = mFboOut.numColorAttachments; i < (unsigned int)mMaxBuffers; i++)
            glFramebufferTextureEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, 0, 0);
        //SoDebugError::postInfo("SoXipFbo", "Attaching 3D color targets %d %d", mFboOut.colorHandles[0], mFboOut.colorHandles[1]);
    }
    else if (mFboOut.colorStorage == GL_RENDERBUFFER_EXT)
    {
        for (unsigned int i = 0; i < mFboOut.numColorAttachments; i++)
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mFboOut.colorHandles[i]);
        for (unsigned int i = mFboOut.numColorAttachments; i < (unsigned int)mMaxBuffers; i++)
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, 0);
    }
}

/**
 *  Deallocation of a buffer.
 */
void SoXipFbo::attachDepth()
{
    // Attach new depth buffer
    if (mFboOut.depthStorage == GL_TEXTURE_2D)
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, mFboOut.depthHandle, 0);
	else if (mFboOut.depthStorage == GL_TEXTURE_3D)
		glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_3D, mFboOut.depthHandle, 0, 0);
    else if (mFboOut.depthStorage == GL_RENDERBUFFER_EXT)
        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mFboOut.depthHandle);
}

/**
 *  Synchronize the output field with the attachment handles.
 */
void SoXipFbo::syncOutputHandles()
{
    bool outputDirty = false;

    if (!mColorHandles || mFboOut.numColorAttachments > 16)
        SoDebugError::post("SoXipFbo", "invalid pointer or more than 16 handles");
    else {
        // Expand list by padding with zeros if to short
        if (colorHandlesOutput.getNum() < (int)mFboOut.numColorAttachments) {
            for (int i = colorHandlesOutput.getNum(); i < (int)mFboOut.numColorAttachments; i++) {
                colorHandlesOutput.set1Value(i, 0);
                outputDirty = true;
            }
        }

        // Update entries if changed
        for (unsigned int i = 0; i < mFboOut.numColorAttachments; i++) {
            if (colorHandlesOutput[i] != mColorHandles[i]) {
                colorHandlesOutput.set1Value(i, static_cast<int>(mColorHandles[i]));
                outputDirty = true;
            }
        }

        // Remove absolete entries
        if (colorHandlesOutput.getNum() > (int)mFboOut.numColorAttachments) {
            colorHandlesOutput.deleteValues(mFboOut.numColorAttachments);
            outputDirty = true;
        }
    }
}

/**
 *  Process any change in color setup.
 *  The clauses could cause the attachments to be bound every frame
 *  but since we only end up in this function when something has
 *  changed this wount happen.
 */
void SoXipFbo::processColorMods()
{
    if (mFboMod.hasModColors)
    {
        if (mIsColorsAllocated)
            deallocateInternalColors();
        attachColors();
        syncOutputHandles();
        //SoDebugError::postInfo("SoXipFbo", "Attached external colors");
    }
    else if (!mFboMod.hasModColors)
    {
        if (!mIsColorsAllocated)
        {
            allocateInternalColors();
            attachColors();
            syncOutputHandles();
            //SoDebugError::postInfo("SoXipFbo", "Attached internal colors");
        }
    }
}

/**
 *  Process any change in depth setup.
 *  The clauses could cause the attachments to be bound every frame
 *  but since we only end up in this function when something has
 *  changed this wount happen.
 */
void SoXipFbo::processDepthMods()
{
    if (mFboMod.hasModDepth)
    {
        if (mIsDepthAllocated)
            deallocateInternalDepth();
        attachDepth();
        //SoDebugError::postInfo("SoXipFbo", "Attached external depth");
    }
    else if (!mFboMod.hasModDepth)
    {
        if (!mIsDepthAllocated)
        {
            allocateInternalDepth();
            attachDepth();
            //SoDebugError::postInfo("SoXipFbo", "Attached internal depth");
        }
    }
}

/**
 *  Sets up and binds the FBO.
 *  1: Set element according to fields.
 *  2: Let children manipulate setup.
 *  3: Allocate/deallocate if need be.
 *  4: Set element according to finished Fbo
 */
void SoXipFbo::GLRender(SoGLRenderAction* action)
{
    //SoDebugError::postInfo(__FUNCTION__, "(1) in mod out (%d %d %d)", mFboIn.isDirty, mFboMod.isDirty, mFboOut.isDirty);

    if (autoSize.getValue()) {
		const SbVec2s &viewportSize = action->getViewportRegion().getViewportSizePixels();
		if (viewportSize != SbVec2s(width.getValue(), height.getValue())) {
			SoDebugError::postInfo("SoXipFbo", "Autosetting FBO size to (%d, %d)", viewportSize[0], viewportSize[1]);
			width.setValue(viewportSize[0]);
			height.setValue(viewportSize[1]);
			mNeedsUpdate = true;
		}
	}

	// Can't use sensors if fields are changed while traversing tree, such as by parent size changing
    if (width.getValue() != mFboIn.width  || height.getValue() != mFboIn.height)
		mNeedsUpdate = true;

    if (mNeedsUpdate)
    {
        // Check number of buffers
        checkMaxNumBuffers();
        // Dealloc if allocated
        if (mIsAllocated)
            deallocate();

        mFboIn.clear();
        mFboMod.clear();
        mFboOut.clear();

        int currUnit = SoXipMultiTextureElement::getCurrentUnit(action->getState());
        int freeUnit = SoXipMultiTextureElement::getFreeUnit(action->getState());
        SoXipMultiTextureElement::setUnit(action->getState(), freeUnit);

        allocateFbo();

        SoXipMultiTextureElement::setUnit(action->getState(), currUnit);

        //SoDebugError::postInfo(__FUNCTION__, "Allocated new Fbo (dirty)");
        mNeedsUpdate = false;
    }
    else
        mFboIn.isDirty = false;

    mFboMod.isDirty = false;

    //SoDebugError::postInfo(__FUNCTION__, "(2) in mod out (%d %d %d)", mFboIn.isDirty, mFboMod.isDirty, mFboOut.isDirty);

    // Send to element and render children to allow modification
    mFboIn.isOpen = true;
    SoXipFboElement::set(action->getState(), this, mFboIn);
    SoXipFboElement::bind(action->getState(), this);

    int currentFbo;
	glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &currentFbo);
    if (!glIsFramebufferEXT(mFboIn.fboHandle) || mFboIn.fboHandle != currentFbo)
    {
        SoDebugError::postWarning("SoXipFbo", "Error in the setup, fbo not guaranteed to be bound");
        mNeedsUpdate = true;
        return;
    }

    //////////
    /// Traverse children
    SoGroup::GLRender(action);
    /// Traverse children
    //////////

    FboSetup * fbo = SoXipFboElement::getActive(action->getState(), this);

    // Detect any change in fbo handle
    if (mFboIn.fboHandle != fbo->fboHandle)
        SoDebugError::postWarning("SoXipFbo",
            "Keep Fbo bound during traversal (%d %d)", mFboIn.fboHandle, fbo->fboHandle);

    //SoDebugError::postInfo(__FUNCTION__, "(3) in mod out (%d %d %d)", mFboIn.isDirty, mFboMod.isDirty, mFboOut.isDirty);

    // Reflect changes if change since last run
    if (mFboMod != *fbo)
    {
        mFboMod = *fbo;
        mFboOut = *fbo;

        int currUnit = SoXipMultiTextureElement::getCurrentUnit(action->getState());
        int freeUnit = SoXipMultiTextureElement::getFreeUnit(action->getState());
        SoXipMultiTextureElement::setUnit(action->getState(), freeUnit);

        processColorMods();
        processDepthMods();

        SoXipMultiTextureElement::setUnit(action->getState(), currUnit);

        mErrorInSetup = false;
    }
    else
        mFboOut.isDirty = false;

    //SoDebugError::postInfo(__FUNCTION__, "(4) in mod out (%d %d %d)", mFboIn.isDirty, mFboMod.isDirty, mFboOut.isDirty);

    SoXipDrawBuffersElement::set(action->getState(), this, mFboOut.numColorAttachments);

    // Everything is now attached so test completeness
    if (!mErrorInSetup)
        mFboOut.isComplete = checkFramebufferStatus();
    if (!mFboOut.isComplete)
        mErrorInSetup = true;

    // Activate FBO element (also sets draw buffer element)
    mFboOut.isOpen = false;
    SoXipFboElement::set(action->getState(), this, mFboOut);

    //SoDebugError::postInfo(__FUNCTION__, "(5) in mod out (%d %d %d)", mFboIn.isDirty, mFboMod.isDirty, mFboOut.isDirty);

    if (!mFboOut.isComplete)
        SoXipDrawBuffersElement::set(action->getState(), this, 0);
}

void SoXipFbo::sensorCB(void *usr, SoSensor *sensor) {
	SoXipFbo * thisObj = reinterpret_cast<SoXipFbo *>(usr);
    thisObj->mNeedsUpdate = true;
#if 0
    if (sensor == thisObj->mColorAttachmentsSensor)
        if (thisObj->colorAttachments.getValue() == 0 && thisObj->mIsAllocated)
            SoDebugError::postWarning("SoXipFbo", "Fbo will be Incomplete without any color attachments");
#endif
}

void SoXipFbo::sensorOutCB(void *usr, SoSensor *sensor) {
    SoXipFbo * fbo = reinterpret_cast<SoXipFbo *>(usr);
    fbo->syncOutputHandles();
}


text:
'use strict';

var request = require('request');
var rp = require('../../../lib/rp.js');

var requestHasNoThen = request('http://localhost:4000/200').then === undefined;
var rpHasThen = rp('http://localhost:4000/200').then !== undefined;

console.log('request: ' + requestHasNoThen + ', rp: ' + rpHasThen);

redpajama_set_name: RedPajamaGithub


text:
namespace demoloop {

void ellipse(GL& gl, const float x, const float y, const float radiusX, const float radiusY, int points = 10);
void circle(GL& gl, const float x, const float y, const float radius, int points = 10);
void rectangle(GL& gl, const float x, const float y, const float w, const float h);
void triangle(GL& gl, const float x1, const float y1, const float x2, const float y2, const float x3, const float y3);
void polygon(GL& gl, const float* xCoords, const float* yCoords, uint32_t count);

void line(GL& gl, const float x1, const float y1, const float x2, const float y2);

}


text:
package br.org.funcate.terramobile.controller.activity.settings;

import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.view.Menu;
import android.view.MenuItem;

/**
 * Activity that shows a Fragment with all the settings of the system
 */
public class SettingsActivity extends PreferenceActivity {

    private SettingsController controller;
    private GPSSettingController gpsSettingController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(getActionBar() != null)
            getActionBar().setDisplayHomeAsUpEnabled(true);
        getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment(), "settings").commit();
        controller = new SettingsController(this);
        gpsSettingController = new GPSSettingController(this);
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        // DON'T DELETE THIS METHOD
        return super.onCreateOptionsMenu(menu);
    }

    /**
     * Logo's click listener
     * @param item
     * @return
     */
    public boolean onOptionsItemSelected(MenuItem item) {
        finish(); // Finish the activity after touch the logo
        return super.onOptionsItemSelected(item);
    }

    public SettingsController getController() {
        return controller;
    }

    public void setController(SettingsController controller) {
        this.controller = controller;
    }

    public GPSSettingController getGPSSettingController() {
        return this.gpsSettingController;
    }
}


text:
namespace GlobExpressions.AST
{
    internal sealed class CharacterWildcard : SubSegment
    {
        public static readonly CharacterWildcard Default = new CharacterWildcard();

        private CharacterWildcard()
            : base(GlobNodeType.CharacterWildcard)
        {
        }

        public override string ToString() => "?";
    }
}


text:
package de.slikey.effectlib.effect;

import de.slikey.effectlib.Effect;
import de.slikey.effectlib.EffectManager;
import de.slikey.effectlib.EffectType;
import org.bukkit.Particle;
import de.slikey.effectlib.util.RandomUtils;
import de.slikey.effectlib.util.VectorUtils;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.util.Vector;

public class AtomEffect extends Effect {

    /**
     * ParticleType of the nucleus
     */
    public Particle particleNucleus = Particle.DRIP_WATER;
    public Color colorNucleus = null;

    /**
     * ParticleType of orbitals
     */
    public Particle particleOrbital = Particle.DRIP_LAVA;
    public Color colorOrbital = null;

    /**
     * Radius of the atom
     */
    public double radius = 3;

    /**
     * Radius of the nucleus as a fraction of the atom-radius
     */
    public float radiusNucleus = .2f;

    /**
     * Particles to be spawned in the nucleus per iteration
     */
    public int particlesNucleus = 10;

    /**
     * Particles to be spawned per orbital per iteration
     */
    public int particlesOrbital = 10;

    /**
     * Orbitals around the nucleus
     */
    public int orbitals = 3;

    /**
     * Rotation around the Y-axis
     */
    public double rotation = 0;

    /**
     * Whether or not to orient to the direction of the source location
     */
    public boolean orient = false;

    /**
     * Velocity of the orbitals
     */
    public double angularVelocity = Math.PI / 80d;

    /**
     * Internal counter
     */
    protected int step = 0;

    public AtomEffect(EffectManager effectManager) {
        super(effectManager);
        type = EffectType.REPEATING;
        period = 2;
        iterations = 200;
    }

    @Override
    public void reset() {
        this.step = 0;
    }

    @Override
    public void onRun() {
        Location location = getLocation();
        for (int i = 0; i < particlesNucleus; i++) {
            Vector v = RandomUtils.getRandomVector().multiply(radius * radiusNucleus);
            if (orient) {
                 v = VectorUtils.rotateVector(v, location);
            }
            location.add(v);
            display(particleNucleus, location, colorNucleus);
            location.subtract(v);
        }
        for (int i = 0; i < particlesOrbital; i++) {
            double angle = step * angularVelocity;
            for (int j = 0; j < orbitals; j++) {
                double xRotation = (Math.PI / orbitals) * j;
                Vector v = new Vector(Math.cos(angle), Math.sin(angle), 0).multiply(radius);
                VectorUtils.rotateAroundAxisX(v, xRotation);
                VectorUtils.rotateAroundAxisY(v, rotation);
                if (orient) {
                     v = VectorUtils.rotateVector(v, location);
                }
                location.add(v);
                display(particleOrbital, location, colorOrbital);
                location.subtract(v);
            }
            step++;
        }
    }

}


text:
package gov.hhs.onc.sdcct.data.parameter;

public interface TokenResourceParam extends TermResourceParam<String> {
}


text:
body {
    padding: 20px;
    border: 2px solid black;
}

table, thead, tbody, td, th {
    text-align:center;
    padding: 5px;
    border-collapse:collapse;
    border: 2px solid black;
}

header {
    text-align: center;
}


text:
<?php

namespace Symfony\Component\DomCrawler\Field;

/**
 * TextareaFormField represents a textarea form field (an HTML textarea tag).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class TextareaFormField extends FormField
{
    /**
     * Initializes the form field.
     *
     * @throws \LogicException When node type is incorrect
     */
    protected function initialize()
    {
        if ('textarea' != $this->node->nodeName) {
            throw new \LogicException(sprintf('A TextareaFormField can only be created from a textarea tag (%s given).', $this->node->nodeName));
        }

        $this->value = null;
        foreach ($this->node->childNodes as $node) {
            $this->value .= $this->document->saveXML($node);
        }
    }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlatRedBall.Input
{
    public class Xbox360DPadReference : I2DInput
    {
        public Xbox360GamePad GamePad { get; set; }
        public float X
        {
            get
            {
                if(GamePad.ButtonDown(Xbox360GamePad.Button.DPadLeft))
                {
                    return -1;
                }
                else if(GamePad.ButtonDown(Xbox360GamePad.Button.DPadRight))
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }

        public float Y
        {
            get
            {
                if (GamePad.ButtonDown(Xbox360GamePad.Button.DPadDown))
                {
                    return -1;
                }
                else if (GamePad.ButtonDown(Xbox360GamePad.Button.DPadUp))
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }

        float I2DInput.XVelocity
        {
            get
            {
                if (GamePad.ButtonPushed(Xbox360GamePad.Button.DPadLeft))
                {
                    return -1 / TimeManager.SecondDifference;
                }
                else if (GamePad.ButtonPushed(Xbox360GamePad.Button.DPadRight))
                {
                    return 1 / TimeManager.SecondDifference;
                }
                else
                {
                    return 0;
                }
            }
        }

        float I2DInput.YVelocity
        {
            get
            {
                if (GamePad.ButtonPushed(Xbox360GamePad.Button.DPadDown))
                {
                    return -1 / TimeManager.SecondDifference;
                }
                else if (GamePad.ButtonPushed(Xbox360GamePad.Button.DPadUp))
                {
                    return 1 / TimeManager.SecondDifference;
                }
                else
                {
                    return 0;
                }
            }
        }

        float I2DInput.Magnitude
        {
            get
            {
                // normally we'd square the components but since they're 0,1 or -2 we just take the sign
                var sum = System.Math.Sign(this.X) + System.Math.Sign(this.Y);

                return (float) System.Math.Sqrt(sum);
            }
        }
    }
}


text:
/**
 * Colorbox Core Style:
 * The following CSS is consistent between example themes and should not be altered.
 */
#colorbox, #cboxOverlay, #cboxWrapper {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 9999;
  overflow: hidden;
}
#cboxOverlay {
  position: fixed;
  width: 100%;
  height: 100%;
}
#cboxMiddleLeft, #cboxBottomLeft {
  clear: left;
}
#cboxContent {
  position: relative;
}
#cboxLoadedContent {
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}
#cboxTitle {
  margin: 0;
}
#cboxLoadingOverlay, #cboxLoadingGraphic {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
/**
 * These elements are buttons, and may need to have additional
 * styles reset to avoid unwanted base styles.
 */
#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow {
  border: 0;
  padding: 0;
  margin: 0;
  overflow: visible;
  width: auto;
  background: none;
  cursor: pointer;
}
/**
 * Avoid outlines on :active (mouseclick),
 * but preserve outlines on :focus (tabbed navigating)
 */
#cboxPrevious:active, #cboxNext:active, #cboxClose:active, #cboxSlideshow:active {
  outline: 0;
}
.cboxPhoto {
  float: left;
  margin: auto;
  border: 0;
  display: block;
  max-width: none;
}
.cboxIframe {
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
}
/* Reset box sizing to content-box if theme is using border-box. */
#colorbox, #cboxContent, #cboxLoadedContent {
  -moz-box-sizing: content-box;
  -webkit-box-sizing: content-box;
  box-sizing: content-box;
}

/**
 * Colorbox module default style:
 * The styles are ordered & tabbed in a way that represents
 * the nesting of the generated HTML.
 */
#cboxOverlay {
  background: #000;
}
#colorbox {
  outline: 0;
}
  #cboxWrapper {
    background: #fff;
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
  }
    #cboxTopLeft {
      width: 15px;
      height: 15px;
    }
    #cboxTopCenter {
      height: 15px;
    }
    #cboxTopRight {
      width: 15px;
      height: 15px;
    }
    #cboxBottomLeft {
      width: 15px;
      height: 10px;
    }
    #cboxBottomCenter {
      height: 10px;
    }
    #cboxBottomRight {
      width: 15px;
      height: 10px;
    }
    #cboxMiddleLeft {
      width: 15px;
    }
    #cboxMiddleRight {
      width: 15px;
    }
    #cboxContent {
      background: #fff;
      overflow: hidden;
    }
      #cboxError {
        padding: 50px;
        border: 1px solid #ccc;
      }
      #cboxLoadedContent {
        margin-bottom: 28px;
      }
      #cboxTitle {
        position: absolute;
        background: rgba(255, 255, 255, 0.7);
        bottom: 28px;
        left: 0;
        color: #535353;
        width: 100%;
        padding: 4px 6px;
        -moz-box-sizing: border-box;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
      }
      #cboxCurrent {
        position: absolute;
        bottom: 4px;
        left: 60px;
        color: #949494;
      }
      .cboxSlideshow_on #cboxSlideshow {
        position: absolute;
        bottom: 0px;
        right: 30px;
        background: url(images/controls.png) no-repeat -75px -50px;
        width: 25px;
        height: 25px;
        text-indent: -9999px;
      }
      .cboxSlideshow_on #cboxSlideshow:hover {
        background-position: -101px -50px;
      }
      .cboxSlideshow_off #cboxSlideshow {
        position: absolute;
        bottom: 0px;
        right: 30px;
        background: url(images/controls.png) no-repeat -25px -50px;
        width: 25px;
        height: 25px;
        text-indent: -9999px;
      }
      .cboxSlideshow_off #cboxSlideshow:hover {
        background-position: -49px -50px;
      }
      #cboxPrevious {
        position: absolute;
        bottom: 0;
        left: 0;
        background: url(images/controls.png) no-repeat -75px 0px;
        width: 25px;
        height: 25px;
        text-indent: -9999px;
      }
      #cboxPrevious:hover {
        background-position: -75px -25px;
      }
      #cboxNext {
        position: absolute;
        bottom: 0;
        left: 27px;
        background: url(images/controls.png) no-repeat -50px 0px;
        width: 25px;
        height: 25px;
        text-indent: -9999px;
      }
      #cboxNext:hover {
        background-position: -50px -25px;
      }
      #cboxLoadingOverlay {
        background: #fff;
      }
      #cboxLoadingGraphic {
        background: url(images/loading_animation.gif) no-repeat center center;
      }
      #cboxClose {
        position: absolute;
        bottom: 0;
        right: 0;
        background: url(images/controls.png) no-repeat -25px 0px;
        width: 25px;
        height: 25px;
        text-indent: -9999px;
      }
      #cboxClose:hover {
        background-position: -25px -25px;
      }


text:
import {toggleAttribute} from '#core/dom';
import * as Preact from '#core/dom/jsx';
import {Layout_Enum} from '#core/dom/layout';

import {Services} from '#service';
import {LocalizedStringId_Enum} from '#service/localization/strings';

import {localizeTemplate} from 'extensions/amp-story/1.0/amp-story-localization-service';
import {HistoryState, setHistoryState} from 'extensions/amp-story/1.0/history';

import {formatI18nNumber, loadFonts} from './amp-story-shopping';
import {
  getShoppingConfig,
  storeShoppingConfig,
} from './amp-story-shopping-config';

import {relativeToSourceUrl} from '../../../src/url';
import {
  Action,
  ShoppingConfigDataDef,
  StateProperty,
} from '../../amp-story/1.0/amp-story-store-service';
import {StoryAnalyticsEvent} from '../../amp-story/1.0/story-analytics';
import {AnalyticsVariable} from '../../amp-story/1.0/variable-service';

/** @const {!Array<!Object>} fontFaces */
const FONTS_TO_LOAD = [
  {
    family: 'Poppins',
    weight: '500',
    src: "url(https://fonts.gstatic.com/s/poppins/v15/pxiByp8kv8JHgFVrLGT9Z1xlFd2JQEk.woff2) format('woff2')",
  },
  {
    family: 'Poppins',
    weight: '600',
    src: "url(https://fonts.gstatic.com/s/poppins/v15/pxiByp8kv8JHgFVrLEj6Z1xlFd2JQEk.woff2) format('woff2')",
  },
];

/**
 * @const {number}
 * Max amount of characters for the product details text section.
 */
const MAX_PRODUCT_DETAILS_TEXT_LENGTH = 3000;

export class AmpStoryShoppingAttachment extends AMP.BaseElement {
  /** @param {!AmpElement} element */
  constructor(element) {
    super(element);

    /** @private {?Element} */
    this.attachmentEl_ = null;

    /** @private {?Element} */
    this.pageEl_ = null;

    /** @private {?Array<!Element>} */
    this.shoppingTags_ = null;

    /** @private @const {!Element} */
    this.templateContainer_ =

;

    /** @private @const {!../../amp-story/1.0/amp-story-store-service.AmpStoryStoreService} */
    this.storeService_ = Services.storyStoreService(this.win);

    /** @private @const {!../../../src/service/localization.LocalizationService} */
    this.localizationService_ = Services.localizationForDoc(this.element);

    /** @private {!Map<string, Element>} */
    this.builtTemplates_ = {};

    /** @private @const {!./story-analytics.StoryAnalyticsService} */
    this.analyticsService_ = Services.storyAnalyticsService(this.win);

    /** @private @const {!./story-analytics.StoryAnalyticsService} */
    this.variableService_ = Services.storyVariableService(this.win);
  }

  /** @override */
  buildCallback() {
    this.pageEl_ = this.element.closest('amp-story-page');
    this.shoppingTags_ = Array.from(
      this.pageEl_.querySelectorAll('amp-story-shopping-tag')
    );

    if (this.shoppingTags_.length === 0) {
      return Promise.reject(
        new Error(`No shopping tags on page ${this.pageEl_.id}.`)
      );
    }

    return getShoppingConfig(this.element, this.pageEl_.id)
      .then((config) => {
        if (Object.keys(config).length === 0) {
          return Promise.reject(
            new Error(`No valid shopping data on page ${this.pageEl_.id}.`)
          );
        }
        storeShoppingConfig(this.pageEl_, config);
      })
      .then(() =>
        this.localizationService_.getLocalizedStringAsync(
          LocalizedStringId_Enum.AMP_STORY_SHOPPING_CTA_LABEL
        )
      )
      .then((ctaText) => {
        this.attachmentEl_ = (
          <amp-story-page-attachment
            layout="nodisplay"
            theme={this.element.getAttribute('theme')}
            cta-text={this.element.getAttribute('cta-text')?.trim() || ctaText}
          >
            {this.templateContainer_}
          </amp-story-page-attachment>
        );
        this.element.appendChild(this.attachmentEl_);
      });
  }

  /** @override */
  layoutCallback() {
    loadFonts(this.win, FONTS_TO_LOAD);
    // Update template on attachment state update or shopping data update.
    this.storeService_.subscribe(
      StateProperty.PAGE_ATTACHMENT_STATE,
      (isOpen) => this.onAttachmentStateUpdate_(isOpen),
      true /** callToInitialize */
    );
    this.storeService_.subscribe(
      StateProperty.SHOPPING_DATA,
      (shoppingData) => this.onShoppingDataUpdate_(shoppingData),
      true /** callToInitialize */
    );
    // Listen to transiton end events on attachment to check to clear active data.
    this.attachmentEl_.addEventListener('transitionend', () =>
      this.clearActiveProductDataIfClosed_()
    );
  }

  /**
   * Triggers template update if opening without active product data.
   * This happens either when the "Shop now" CTA is clicked or when a
   * shopping tag is clicked.
   * @param {boolean} isOpen
   * @private
   */
  onAttachmentStateUpdate_(isOpen) {
    if (!this.isOnActivePage_() || !isOpen) {
      return;
    }

    const shoppingData = this.storeService_.get(StateProperty.SHOPPING_DATA);

    if (!shoppingData.activeProductData) {
      this.updateTemplate_(shoppingData);
    }
  }

  /**
   * Handles template changes when there is activeProductData.
   * This happens when a product tag or PLP card is clicked.
   * @param {!Object<string, !ShoppingConfigDataDef>} shoppingData
   * @private
   */
  onShoppingDataUpdate_(shoppingData) {
    if (!shoppingData.activeProductData || !this.isOnActivePage_()) {
      return;
    }
    const isOpen = this.storeService_.get(StateProperty.PAGE_ATTACHMENT_STATE);
    if (isOpen) {
      // If open, update the template.
      // This happens when a product card is clicked in the PLP template.
      this.updateTemplate_(shoppingData);
    } else {
      // Otherwise, open the attachment and then update the template.
      // This happens when clicking a shopping tag.
      this.attachmentEl_.getImpl().then((impl) => {
        impl.open();
        this.updateTemplate_(shoppingData);
      });
    }
  }

  /**
   * Clear active product data after the attachment closes so that content does not jump.
   * @private
   */
  clearActiveProductDataIfClosed_() {
    const isOpen = this.storeService_.get(StateProperty.PAGE_ATTACHMENT_STATE);
    if (!isOpen) {
      this.storeService_.dispatch(Action.ADD_SHOPPING_DATA, {
        'activeProductData': null,
      });
    }
  }

  /**
   * Updates template based on shopping data.
   * @param {!Object<string, !ShoppingConfigDataDef>} shoppingData
   * @private
   */
  updateTemplate_(shoppingData) {
    const productOnPageToConfig = shoppingData[this.pageEl_.id];
    const shoppingDataPerPage = Object.values(productOnPageToConfig);

    let productForPdp = shoppingData.activeProductData;
    // If no active product and only one product on page, use the one product for the PDP.
    if (!productForPdp && shoppingDataPerPage.length === 1) {
      productForPdp = shoppingDataPerPage[0];
    }

    // templateId string used to key already built templates.
    const templateId = productForPdp ? `pdp-${productForPdp.productId}` : 'plp';

    // Remove active attribute from already built templates.
    Object.values(this.builtTemplates_).forEach((template) =>
      template.removeAttribute('active')
    );

    const template = this.getTemplate_(
      templateId,
      productForPdp,
      shoppingDataPerPage
    );
    template.setAttribute('active', '');
    this.resetScroll_(template);

    // Ensure details text is closed, unless there is only one product on the page.
    const detailsContainer = template.querySelector(
      '.i-amphtml-amp-story-shopping-pdp-details'
    );
    if (detailsContainer) {
      const shouldOpen = shoppingDataPerPage.length === 1;
      this.toggleDetailsText_(detailsContainer, shouldOpen);
    }

    // If template has not been appended to the dom, append it and assign it to built templates.
    if (!template.isConnected) {
      this.builtTemplates_[templateId] = template;
      this.mutateElement(() => this.templateContainer_.appendChild(template));
    }

    // PDP view that calls the analytics service sending the product id.
    if (productForPdp) {
      this.variableService_.onVariableUpdate(
        AnalyticsVariable.STORY_SHOPPING_PRODUCT_ID,
        productForPdp.productId
      );
    }

    // Triggers an analytics event for the PDP or PLP depending on if there is an active product.
    this.analyticsService_.triggerEvent(
      productForPdp
        ? StoryAnalyticsEvent.SHOPPING_PDP_VIEW
        : StoryAnalyticsEvent.SHOPPING_PLP_VIEW
    );
  }

  /**
   * Returns template if already built. If not built, returns a built template.
   * @param {string} templateId
   * @param {?ShoppingConfigDataDef} productForPdp
   * @param {!Array<!ShoppingConfigDataDef} shoppingDataForPage
   * @return {Element}
   * @private
   */
  getTemplate_(templateId, productForPdp, shoppingDataForPage) {
    if (this.builtTemplates_[templateId]) {
      return this.builtTemplates_[templateId];
    }
    const template = (

        {/* If there is a product for the PDP, render PDP. */}
        {productForPdp && this.renderPdpTemplate_(productForPdp)}
        {/* If there is more than one product on the page, render PLP. */}
        {shoppingDataForPage.length > 1 &&
          this.renderPlpTemplate_(
            shoppingDataForPage.filter((item) => item !== productForPdp)
          )}

    );
    localizeTemplate(template, this.element);
    return template;
  }

  /**
   * Centers carousel card image on click.
   * @param {!Element} carouselCard
   * @private
   */
  onPdpCarouselCardClick_(carouselCard) {
    carouselCard./*OK*/ scrollIntoView({
      behavior: 'smooth',
      block: 'nearest',
      inline: 'center',
    });
  }

  /**
   * On plp card click dispatch shopping data.
   * @param {!Array<!ShoppingConfigDataDef>} shoppingData
   * @private
   */
  onPlpCardClick_(shoppingData) {
    this.storeService_.dispatch(Action.ADD_SHOPPING_DATA, {
      'activeProductData': shoppingData,
    });

    setHistoryState(this.win, HistoryState.SHOPPING_DATA, shoppingData);
  }

  /**
   * @param {!Element} template
   * @private
   */
  resetScroll_(template) {
    // If template contains carousel, reset carousel scroll.
    template
      .querySelector('.i-amphtml-amp-story-shopping-pdp-carousel')
      ?.scroll({
        left: 0,
      });
    // Smooth scroll drawer to top.
    this.element
      .querySelector('.i-amphtml-story-draggable-drawer-container')
      .scroll({
        top: 0,
        behavior: 'smooth',
      });
  }

  /**
   * Expands or collapses details text.
   * @param {!Element} detailsContainer
   * @param {boolean} shouldOpen
   * @private
   */
  toggleDetailsText_(detailsContainer, shouldOpen) {
    const detailsText = detailsContainer.querySelector(
      '.i-amphtml-amp-story-shopping-pdp-details-text'
    );
    this.mutateElement(() => {
      toggleAttribute(detailsContainer, 'active', shouldOpen);
      detailsText.setAttribute('aria-hidden', !shouldOpen);
    });
  }

  /**
   * onclick event that fires when buy now is clicked,
   * sends an analytics event containing product id.
   * @return {boolean}
   * @private
   */
  onClickBuyNow_() {
    this.analyticsService_.triggerEvent(
      StoryAnalyticsEvent.SHOPPING_BUY_NOW_CLICK
    );
  }

  /**
   * @param {!ShoppingConfigDataDef} activeProductData
   * @return {Element}
   * @private
   */
  renderPdpTemplate_(activeProductData) {
    const onDetailsHeaderClick = (el) => {
      const detailsContainer = el.closest(
        '.i-amphtml-amp-story-shopping-pdp-details'
      );
      const shouldOpen = !detailsContainer.hasAttribute('active');
      this.toggleDetailsText_(detailsContainer, shouldOpen);
    };
    return (

          {activeProductData.productBrand && (

              {activeProductData.productBrand}

          )}

              {activeProductData.productTitle}

              {formatI18nNumber(
                this.localizationService_,
                this.element,
                activeProductData.productPriceCurrency,
                activeProductData.productPrice
              )}

          {activeProductData.aggregateRating && (
            // Wrapper prevents anchor from spanning entire width of container.
            // This prevents accidental clicks.

                {activeProductData.aggregateRating.ratingValue}

                  {activeProductData.aggregateRating.reviewCount}

          )}
           this.onClickBuyNow_()}
            i-amphtml-i18n-text-content={
              LocalizedStringId_Enum.AMP_STORY_SHOPPING_ATTACHMENT_CTA_LABEL
            }
          >

          {activeProductData.productImages.map((image) => (

 this.onPdpCarouselCardClick_(e.target)}
            >

          ))}

        {activeProductData.productDetails && (

            <button
              class="i-amphtml-amp-story-shopping-button-reset i-amphtml-amp-story-shopping-pdp-details-header"
              onClick={(e) => onDetailsHeaderClick(e.target)}
            >

              <svg
                viewBox="0 0 10 6"
                class="i-amphtml-amp-story-shopping-pdp-details-header-arrow"
              >
                <path d="M.5,.5 L5,5.2 L9.5,.5" />
              </svg>
            </button>

              {
                // Add ellipses if product details text is greater than max.
                (activeProductData.productDetails.length >
                MAX_PRODUCT_DETAILS_TEXT_LENGTH
                  ? activeProductData.productDetails.slice(
                      0,
                      MAX_PRODUCT_DETAILS_TEXT_LENGTH
                    ) + '...'
                  : activeProductData.productDetails
                )
                  // Replaces two newlines with 0 or more spaces between them with two newlines.
                  .replace(/\n\s*\n/g, '\n\n')
              }

        )}

    );
  }

  /**
   * @param {!Array<!ShoppingConfigDataDef>} shoppingDataForPage
   * @return {Element}
   * @private
   */
  renderPlpTemplate_(shoppingDataForPage) {
    return (

          {shoppingDataForPage.map((data) => (
            <button
              class="i-amphtml-amp-story-shopping-button-reset i-amphtml-amp-story-shopping-plp-card"
              role="button"
              onClick={() => this.onPlpCardClick_(data)}
            >

              {data['productBrand'] && (

                  {data['productBrand']}

              )}

                {data['productTitle']}

                {formatI18nNumber(
                  this.localizationService_,
                  this.element,
                  data['productPriceCurrency'],
                  data['productPrice']
                )}

            </button>
          ))}

    );
  }

  /**
   * @return {boolean}
   * @private
   */
  isOnActivePage_() {
    return (
      this.pageEl_.id === this.storeService_.get(StateProperty.CURRENT_PAGE_ID)
    );
  }

  /** @override */
  isLayoutSupported(layout) {
    return layout == Layout_Enum.CONTAINER;
  }
}


text:
<!DOCTYPE HTML>

	<meta http-equiv="content-type" content="text/html; charset=utf-8" />

	<title>JsDoc Reference - File Index</title>
	<meta name="generator" content="JsDoc Toolkit" />

	<link media="all" rel="stylesheet" href="css/common.css" type="text/css" />
	<link media="all" rel="stylesheet" href="css/prettify.css" type="text/css" />
	<link media="all" rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
	<link media="print" rel="stylesheet" href="css/print.css" type="text/css" />

				JsDoc Reference

Class Index

File Index

Classes

$

fn

swipe

defaults

directions

fingers

pageScroll

phases

_global_

File Index

jquery.touchSwipe.js

						No description.

Documentation generated by JsDoc Toolkit 2.4.0 on Wed Jun 04 2014 13:36:57 GMT+0100 (BST)


text:
'use strict';

angular.module('observatory3App')
  .controller('ForgotPasswordCtrl', function ($scope, Auth) {
    $scope.user = {};
    $scope.errors = {};

    $scope.forgotPassword = function(form) {
      $scope.submitted = true;

      if(form.$valid) {
        Auth.resetPassword($scope.user.email, function(err){
          if (err){
            $scope.errors.other = err;
          }else{
            $scope.success = true;
          }
        });
      }
    };

  });


text:
<?php

namespace PhpOffice\PhpWord\Writer\ODText\Element;

use PhpOffice\PhpWord\Element\TrackChange;
use PhpOffice\PhpWord\Exception\Exception;

/**
 * Text element writer
 *
 * @since 0.10.0
 */
class Text extends AbstractElement
{
    /**
     * Write element
     */
    public function write()
    {
        $xmlWriter = $this->getXmlWriter();
        $element = $this->getElement();
        if (!$element instanceof \PhpOffice\PhpWord\Element\Text) {
            return;
        }
        $fontStyle = $element->getFontStyle();
        $paragraphStyle = $element->getParagraphStyle();

        // @todo Commented for TextRun. Should really checkout this value
        // $fStyleIsObject = ($fontStyle instanceof Font) ? true : false;
        $fStyleIsObject = false;

        if ($fStyleIsObject) {
            // Don't never be the case, because I browse all sections for cleaning all styles not declared
            throw new Exception('PhpWord : $fStyleIsObject wouldn\'t be an object');
        }

        if (!$this->withoutP) {
            $xmlWriter->startElement('text:p'); // text:p
        }
        if ($element->getTrackChange() != null && $element->getTrackChange()->getChangeType() == TrackChange::DELETED) {
            $xmlWriter->startElement('text:change');
            $xmlWriter->writeAttribute('text:change-id', $element->getTrackChange()->getElementId());
            $xmlWriter->endElement();
        } else {
            if (empty($fontStyle)) {
                if (empty($paragraphStyle)) {
                    $xmlWriter->writeAttribute('text:style-name', 'P1');
                } elseif (is_string($paragraphStyle)) {
                    $xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
                }
                $this->writeChangeInsertion(true, $element->getTrackChange());
                $this->writeText($element->getText());
                $this->writeChangeInsertion(false, $element->getTrackChange());
            } else {
                if (empty($paragraphStyle)) {
                    $xmlWriter->writeAttribute('text:style-name', 'Standard');
                } elseif (is_string($paragraphStyle)) {
                    $xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
                }
                // text:span
                $xmlWriter->startElement('text:span');
                if (is_string($fontStyle)) {
                    $xmlWriter->writeAttribute('text:style-name', $fontStyle);
                }
                $this->writeChangeInsertion(true, $element->getTrackChange());
                $this->writeText($element->getText());
                $this->writeChangeInsertion(false, $element->getTrackChange());
                $xmlWriter->endElement();
            }
        }
        if (!$this->withoutP) {
            $xmlWriter->endElement(); // text:p
        }
    }

    private function writeChangeInsertion($start = true, TrackChange $trackChange = null)
    {
        if ($trackChange == null || $trackChange->getChangeType() != TrackChange::INSERTED) {
            return;
        }
        $xmlWriter = $this->getXmlWriter();
        $xmlWriter->startElement('text:change-' . ($start ? 'start' : 'end'));
        $xmlWriter->writeAttribute('text:change-id', $trackChange->getElementId());
        $xmlWriter->endElement();
    }
}