TextBlock::TextBlock(
        std::string id,
        std::string styleName,
        Element* pParent,
        Layout const * pLayout,
        Frame* pFrame,
        AssetManager* pAssetManager,
        NotificationQueue* pNotificationQueue,
        float relativeScale,
        float border,
        bool dimmable,
        bool adaptiveScaling,
        bool consumeInput,
        float innerBorder,
        FontSize fontSize,
        TextFlowAlignment alignment,
        TextFlowVerticalAlignment verticalAlignment,
        std::u16string content,
        std::string key) : Block(
            id,
            styleName,
            pParent,
            pLayout,
            pFrame,
            pAssetManager,
            pNotificationQueue,
            relativeScale,
            border,
            dimmable,
            adaptiveScaling,
            consumeInput,
            innerBorder)
    {
        mType = Type::TEXT_BLOCK;

        // Fill members
        mKey = key;

        // Create text flow
        if (mKey != EMPTY_STRING_ATTRIBUTE)
        {
            std::u16string localization = mpLayout->getContentFromLocalization(mKey);
            if (localization == LOCALIZATION_NOT_FOUND)
            {
                throwWarning(
                    OperationNotifier::Operation::RUNTIME,
                    "No localization used or one found for following key: " + mKey + ". Element has following id: " + getId());

                mupTextFlow = std::move(mpAssetManager->createTextFlow(fontSize, alignment, verticalAlignment, content));
            }
            else
            {
                mupTextFlow = std::move(mpAssetManager->createTextFlow(fontSize, alignment, verticalAlignment, localization));
            }
        }
        else
        {
            mupTextFlow = std::move(mpAssetManager->createTextFlow(fontSize, alignment, verticalAlignment, content));
        }
    }
    void WordSuggest::specialPipeNotification(NotificationType notification, Layout* pLayout)
    {
        // Pipe notifications to notifier template including own data
        switch (notification)
        {
        case NotificationType::WORD_SUGGEST_CHOSEN:
        {
            // Notify listener method with UTF-16 string
            notifyListener(&WordSuggestListener::chosen, pLayout, getId(), mLastChosenSuggestion);

            // Convert suggestion value to UTF-8 string
            std::string lastChosenSuggestionValue8;
            convertUTF16ToUTF8(mLastChosenSuggestion, lastChosenSuggestionValue8);

            // Notify listener method with UTF-8 string
            notifyListener(&WordSuggestListener::chosen, pLayout, getId(), lastChosenSuggestionValue8);
            break;
        }
        default:
            throwWarning(
                OperationNotifier::Operation::BUG,
                "Word suggest got notification which is not thought for it.");
            break;
        }
    }
Esempio n. 3
0
void Operation::cleanup()
{
    if(fileType() == File)
    {
        if(!QFile(dataFilename()).remove())
            throwWarning(QObject::tr("Unable to remove temporary file %1").arg(dataFilename()));
    }
}
Esempio n. 4
0
    TextFlow::Word TextFlow::calculateWord(std::u16string content, float scale) const
    {
        // Empty word
        Word word;
        word.spVertices = std::shared_ptr<std::vector<glm::vec3> >(new std::vector<glm::vec3>);
        word.spTextureCoordinates = std::shared_ptr<std::vector<glm::vec2> >(new std::vector<glm::vec2>);

        // Fill word with data
        float xPixelPen = 0;
        for (uint i = 0; i < content.size(); i++)
        {
            Glyph const * pGlyph = mpFont->getGlyph(mFontSize, content[i]);
            if (pGlyph == NULL)
            {
                throwWarning(
                    OperationNotifier::Operation::RUNTIME,
                    "TextFlow has character in content not covered by character set");
                continue;
            }

            float yPixelPen = 0 - (scale * (float)(pGlyph->size.y - pGlyph->bearing.y));

            // Vertices for this quad
            glm::vec3 vertexA = glm::vec3(xPixelPen, yPixelPen, 0);
            glm::vec3 vertexB = glm::vec3(xPixelPen + (scale * pGlyph->size.x), yPixelPen, 0);
            glm::vec3 vertexC = glm::vec3(xPixelPen + (scale * pGlyph->size.x), yPixelPen + (scale * pGlyph->size.y), 0);
            glm::vec3 vertexD = glm::vec3(xPixelPen, yPixelPen + (scale * pGlyph->size.y), 0);

            // Texture coordinates for this quad
            glm::vec2 textureCoordinateA = glm::vec2(pGlyph->atlasPosition.x, pGlyph->atlasPosition.y);
            glm::vec2 textureCoordinateB = glm::vec2(pGlyph->atlasPosition.z, pGlyph->atlasPosition.y);
            glm::vec2 textureCoordinateC = glm::vec2(pGlyph->atlasPosition.z, pGlyph->atlasPosition.w);
            glm::vec2 textureCoordinateD = glm::vec2(pGlyph->atlasPosition.x, pGlyph->atlasPosition.w);

            xPixelPen += scale * pGlyph->advance.x;

            // Fill into data blocks
            word.spVertices->push_back(vertexA);
            word.spVertices->push_back(vertexB);
            word.spVertices->push_back(vertexC);
            word.spVertices->push_back(vertexC);
            word.spVertices->push_back(vertexD);
            word.spVertices->push_back(vertexA);

            word.spTextureCoordinates->push_back(textureCoordinateA);
            word.spTextureCoordinates->push_back(textureCoordinateB);
            word.spTextureCoordinates->push_back(textureCoordinateC);
            word.spTextureCoordinates->push_back(textureCoordinateC);
            word.spTextureCoordinates->push_back(textureCoordinateD);
            word.spTextureCoordinates->push_back(textureCoordinateA);
        }

        // Set width of whole word
        word.pixelWidth = xPixelPen;

        return word;
    }
Esempio n. 5
0
 void terminateGUI(GUI* pGUI)
 {
     if (pGUI != NULL)
     {
         delete pGUI;
         pGUI = NULL;
     }
     else
     {
         throwWarning(OperationNotifier::Operation::RUNTIME, "GUI was tried to terminate but is already terminated");
     }
 }
Esempio n. 6
0
void RemoveOperation::applyData()
{
    QFileInfo fileInfo(localFilename());
    if(fileInfo.isFile() && !QFile::remove(localFilename()))
    {
        throwWarning(QObject::tr("Failed to remove file"));
    }
    else
    {
        qCDebug(LOG_RMFILEOP) << "File removed" << path();
    }
}
    void Element::setStyle(std::string styleName)
    {
        Style const * pStyle = mpLayout->getStyleFromStylesheet(styleName);

        if(pStyle != NULL)
        {
            mpStyle = pStyle;
        }
        else
        {
            throwWarning(OperationNotifier::Operation::RUNTIME, "Cannot find style with name: " + styleName);
        }
    }
 void TextBlock::setContent(std::u16string content)
 {
     // Check whether value from key is in use
     if (mKey != EMPTY_STRING_ATTRIBUTE && mpLayout->getContentFromLocalization(mKey) == LOCALIZATION_NOT_FOUND)
     {
         throwWarning(
             OperationNotifier::Operation::RUNTIME,
             "Content of TextBlock could not be set because value from key is in use");
     }
     else
     {
         mupTextFlow->setContent(content);
     }
 }
 void TextBlock::setContent(std::u16string content)
 {
     // TODO: somehow strange, maybe save the usage of the key in a bool
     if (mKey != EMPTY_STRING_ATTRIBUTE && mpLayout->getContentFromLocalization(mKey) != LOCALIZATION_NOT_FOUND)
     {
         throwWarning(
             OperationNotifier::Operation::RUNTIME,
             "Content of TextBlock could not be set because value from key is in use");
     }
     else
     {
         mupTextFlow->setContent(content);
     }
 }
    PixelTexture::PixelTexture(
		std::string filepath,
		Filtering filtering,
		Wrap wrap,
		int suspectedChannels) : Texture()
    {
        // Setup stb_image
        stbi_set_flip_vertically_on_load(true);

        // Try to load image
        int width, height, channelCount;
        unsigned char* data = stbi_load(buildPath(filepath).c_str(), &width, &height, &channelCount, suspectedChannels);

        // Check whether file was found and parsed
        if (data == NULL)
        {
            throwError(OperationNotifier::Operation::IMAGE_LOADING, "Image file not found or error at parsing", filepath);
        }

		// Decide format
		GLenum glFormat;
		GLenum glInternalFormat;
		switch (suspectedChannels)
		{
		case 1:
			glFormat = GL_RED;
			glInternalFormat = GL_R8;
			break;
		case 3:
			glFormat = GL_RGB;
			glInternalFormat = GL_RGB8;
			break;
		case 4:
			glFormat = GL_RGBA;
			glInternalFormat = GL_RGBA8;
			break;
		default:
			glFormat= GL_RGB; 
			glInternalFormat = GL_R8;
			throwWarning(OperationNotifier::Operation::IMAGE_LOADING, "Unknown number of color channels", filepath);
			break;
		}

        // Create OpenGL texture
        createOpenGLTexture(data, filtering, wrap, width, height, channelCount, glFormat, glInternalFormat, false, filepath);

        // Delete raw image data
        stbi_image_free(data);
    }
 void TextBlock::setKey(std::string key)
 {
     if (key == EMPTY_STRING_ATTRIBUTE)
     {
         throwWarning(
             OperationNotifier::Operation::RUNTIME,
             "Tried to use empty key for localization");
     }
     else
     {
         std::u16string localization = mpLayout->getContentFromLocalization(key);
         if (localization == LOCALIZATION_NOT_FOUND)
         {
             throwWarning(
                 OperationNotifier::Operation::RUNTIME,
                 "No localization found for following key: " + key + ". Element has following id: " + getId());
         }
         else
         {
             mKey = key;
             mupTextFlow->setContent(localization);
         }
     }
 }
	void Sensor::specialPipeNotification(Notification notification, Layout* pLayout)
	{
		// Pipe notifications to notifier template including own data
		switch (notification)
		{
		case Notification::SENSOR_PENETRATED:
			notifyListener(&SensorListener::penetrated, pLayout, getId(), mPenetration.getValue());
			break;
		default:
			throwWarning(
				OperationNotifier::Operation::BUG,
				"Sensor got notification which is not thought for it.");
			break;
		}
	}
 void Button::specialPipeNotification(NotificationType notification, Layout* pLayout)
 {
     // Pipe notifications to notifier template including own data
     switch (notification)
     {
     case NotificationType::BUTTON_HIT:
         notifyListener(&ButtonListener::hit, pLayout, getId());
         break;
     case NotificationType::BUTTON_DOWN:
         notifyListener(&ButtonListener::down, pLayout, getId());
         break;
     case NotificationType::BUTTON_UP:
         notifyListener(&ButtonListener::up, pLayout, getId());
         break;
     default:
         throwWarning(
             OperationNotifier::Operation::BUG,
             "Button got notification which is not thought for it.");
         break;
     }
 }
    void TextFlow::specialCalculateMesh(
            std::u16string streamlinedContent,
            float lineHeight, std::vector<glm::vec3>& rVertices,
            std::vector<glm::vec2>& rTextureCoordinates)
    {
		// Reset flow width to get longest line's width of this computation
		mFlowWidth = 0;

        // OpenGL setup done in calling method

        // Get size of space character
        float pixelOfSpace = 0;

        Glyph const * pGlyph = mpFont->getGlyph(mFontSize, u' ');
        if (pGlyph == NULL)
        {
            throwWarning(
                OperationNotifier::Operation::RUNTIME,
                "TextFlow creation does not find space sign in font");
        }
        else
        {
            pixelOfSpace = mScale * pGlyph->advance.x;
        }

        // Create mark for overflow
        Word overflowMark = calculateWord(TEXT_FLOW_OVERFLOW_MARK, mScale);

        // Get pararaphs separated by \n
        std::vector<std::u16string> paragraphs;
        std::u16string paragraphDelimiter = u"\n";

        // Seperate into paragraphs
        size_t pos = 0;
        std::u16string token;
        while ((pos = streamlinedContent.find(paragraphDelimiter)) != std::u16string::npos)
        {
            token = streamlinedContent.substr(0, pos);
            paragraphs.push_back(token);
            streamlinedContent.erase(0, pos + paragraphDelimiter.length());
        }
        paragraphs.push_back(streamlinedContent); // Last paragraph (paragraphs never empty)

        // Do not generate text flow mesh when there is a failure
        bool failure = false;

        // Go over paragraphs (pens are in local pixel coordinate system with origin in lower left corner of element)
        float yPixelPen = -lineHeight; // First line should be also inside flow
        for (std::u16string& rPargraph : paragraphs)
        {
            // Get words out of paragraph
            std::vector<Word> words;
            std::u16string wordDelimiter = u" ";
            while ((pos = rPargraph.find(wordDelimiter)) != std::u16string::npos)
            {
                token = rPargraph.substr(0, pos);
                rPargraph.erase(0, pos + wordDelimiter.length());
                failure |= !insertFitWord(words, token, mWidth, mScale);
            }

            // Add last token from paragraph as well
            failure |= !insertFitWord(words, rPargraph, mWidth, mScale);

            // Failure appeared, forget it
            if (!failure)
            {
                // Prepare some values
                uint wordIndex = 0;
                bool hasNext = !words.empty();

                // Go over lines to write paragraph
                while (hasNext && abs(yPixelPen) <= mHeight)
                {
                    // Collect words in one line
                    std::vector<Word const *> line;
                    float wordsPixelWidth = 0;
                    float newWordsWithSpacesPixelWidth = 0;

                    // Still words in the paragraph and enough space? Fill into line!
                    while (hasNext && newWordsWithSpacesPixelWidth <= mWidth)
                    {
                        // First word should always fit into width because of previous checks
                        wordsPixelWidth += words[wordIndex].pixelWidth;
                        line.push_back(&words[wordIndex]);
                        wordIndex++;

                        if (wordIndex >= words.size())
                        {
                            // No words in paragraph left
                            hasNext = false;
                        }
                        else
                        {
                            // Calculate next width of line
                            newWordsWithSpacesPixelWidth = std::ceil(
                                (wordsPixelWidth + (float)words[wordIndex].pixelWidth) // Words size (old ones and new one)
                                + (((float)line.size()) - 1.0f) * pixelOfSpace); // Spaces between words
                        }
                    }

                    // If this is last line and after it still words left, replace it by some mark for overflow
                    if (hasNext && abs(yPixelPen - lineHeight) > mHeight && overflowMark.pixelWidth <= mWidth)
                    {
                        line.clear();
                        wordsPixelWidth = overflowMark.pixelWidth;
                        line.push_back(&overflowMark);
                    }

					// Remember longest line's width
					mFlowWidth = mFlowWidth < ((int) wordsPixelWidth + 1) ? ((int)wordsPixelWidth + 1) : mFlowWidth;

                    // Decide dynamic space for line
                    float dynamicSpace = pixelOfSpace;
                    if (line.size() > 1)
                    {
                        if (mAlignment == TextFlowAlignment::JUSTIFY && hasNext && line.size() > 1) // Do not use dynamic space for last line
                        {
                            // For justify, do something dynamic
                            dynamicSpace = ((float)mWidth - wordsPixelWidth) / ((float)line.size() - 1.0f);
                        }
                        else
                        {
                            // Adjust space to compensate precision errors in other alignments
                            float calculatedDynamicSpace = (float)mWidth - (wordsPixelWidth / (float)(line.size() - 1));
                            dynamicSpace = std::min(dynamicSpace, calculatedDynamicSpace);
                        }
                    }

                    // Now decide xOffset for line
                    float xOffset = 0;
                    if (mAlignment == TextFlowAlignment::RIGHT || mAlignment == TextFlowAlignment::CENTER)
                    {
                        xOffset = (float)mWidth - ((wordsPixelWidth + ((float)line.size() - 1.0f) * dynamicSpace));
                        if (mAlignment == TextFlowAlignment::CENTER)
                        {
                            xOffset = xOffset / 2.0f;
                        }
                    }

                    // Combine word geometry to one line
                    float xPixelPen = xOffset;
                    for (uint i = 0; i < line.size(); i++)
                    {
                        // Assuming, that the count of vertices and texture coordinates is equal
                        for (uint j = 0; j < line[i]->spVertices->size(); j++)
                        {
                            const glm::vec3& rVertex = line[i]->spVertices->at(j);
                            rVertices.push_back(glm::vec3(rVertex.x + xPixelPen, rVertex.y + yPixelPen, rVertex.z));
                            const glm::vec2& rTextureCoordinate = line[i]->spTextureCoordinates->at(j);
                            rTextureCoordinates.push_back(glm::vec2(rTextureCoordinate.s, rTextureCoordinate.t));
                        }

                        // Advance xPen
                        xPixelPen += dynamicSpace + line[i]->pixelWidth;
                    }

                    // Advance yPen
                    yPixelPen -= lineHeight;
                }
            }
        }

        // If failure appeared, clean up
        if (failure)
        {
            // Vertex count will become zero
            rVertices.clear();
            rTextureCoordinates.clear();
        }

        // Get height of all lines (yPixelPen is one line to low now)
        mFlowHeight = (int)std::max(std::ceil(abs(yPixelPen) - lineHeight), 0.0f);
    }