void setTextFormatProperties (const AttributedString& text, IDWriteTextFormat* const format)
    {
        DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
        DWRITE_WORD_WRAPPING wrapType = DWRITE_WORD_WRAPPING_WRAP;

        switch (text.getJustification().getOnlyHorizontalFlags())
        {
            case Justification::left:                   break;
            case Justification::right:                  alignment = DWRITE_TEXT_ALIGNMENT_TRAILING; break;
            case Justification::horizontallyCentred:    alignment = DWRITE_TEXT_ALIGNMENT_CENTER; break;
            case Justification::horizontallyJustified:  break; // DirectWrite cannot justify text, default to left alignment
            default:                                    jassertfalse; break; // Illegal justification flags
        }

        switch (text.getWordWrap())
        {
            case AttributedString::none:      wrapType = DWRITE_WORD_WRAPPING_NO_WRAP; break;
            case AttributedString::byWord:    break;
            case AttributedString::byChar:    break; // DirectWrite doesn't support wrapping by character, default to word-wrap
            default:                          jassertfalse; break; // Illegal flags!
        }

        format->SetTextAlignment (alignment);
        format->SetWordWrapping (wrapType);

        // DirectWrite does not automatically set reading direction
        // This must be set correctly and manually when using RTL Scripts (Hebrew, Arabic)
        if (text.getReadingDirection() == AttributedString::rightToLeft)
            format->SetReadingDirection (DWRITE_READING_DIRECTION_RIGHT_TO_LEFT);
    }
Ejemplo n.º 2
0
    void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool rowIsSelected) override
    {
        if (rowIsSelected)
            g.fillAll (Colours::deepskyblue);

        if (JuceDemoTypeBase* type = JuceDemoTypeBase::getDemoTypeList() [rowNumber])
        {
            String name (type->name.trimCharactersAtStart ("0123456789").trimStart());

            AttributedString a;
            a.setJustification (Justification::centredLeft);

            String category;

            if (name.containsChar (':'))
            {
                category = name.upToFirstOccurrenceOf (":", true, false);
                name = name.fromFirstOccurrenceOf (":", false, false).trim();

                if (height > 20)
                    category << "\n";
                else
                    category << " ";
            }

            if (category.isNotEmpty())
                a.append (category, Font (10.0f), Colour::greyLevel (0.5f));

            a.append (name, Font (13.0f), Colours::white.withAlpha (0.9f));

            a.draw (g, Rectangle<int> (width + 10, height).reduced (6, 0).toFloat());
        }
    }
Ejemplo n.º 3
0
void NodeComponent::bubbleMessage(String msg)
{
  AttributedString text (msg);
  text.setJustification (Justification::centred);
  bbl.setAlwaysOnTop (true);
  bbl.addToDesktop (0);
  
  bbl.showAt(this, text, 5000., true, false);
}
Ejemplo n.º 4
0
    void updateLayout (const int width)
    {
        AttributedString s;
        s.setJustification (Justification::topLeft);
        s.append (getText(), getFont());

        TextLayout text;
        text.createLayoutWithBalancedLineLengths (s, width - 8.0f);
        setSize (width, jmin (width, (int) (text.getHeight() + getFont().getHeight())));
    }
Ejemplo n.º 5
0
void FilterComponent::bubbleMessage(String msg)
{
  BubbleMessageComponent* bbl = new BubbleMessageComponent();
  AttributedString text (msg);
  text.setJustification (Justification::centred);
  bbl->setAlwaysOnTop (true);
  bbl->addToDesktop (0);
  
  bbl->showAt(this, text, 2000., true, true);
}
    bool setupLayout (const AttributedString& text, const float maxWidth, const float maxHeight,
                      ID2D1RenderTarget& renderTarget, IDWriteFactory& directWriteFactory,
                      IDWriteFontCollection& fontCollection, ComSmartPtr<IDWriteTextLayout>& textLayout)
    {
        // To add color to text, we need to create a D2D render target
        // Since we are not actually rendering to a D2D context we create a temporary GDI render target

        Font defaultFont;
        BOOL fontFound = false;
        uint32 fontIndex;
        fontCollection.FindFamilyName (defaultFont.getTypeface()->getName().toWideCharPointer(), &fontIndex, &fontFound);

        if (! fontFound)
            fontIndex = 0;

        ComSmartPtr<IDWriteFontFamily> dwFontFamily;
        HRESULT hr = fontCollection.GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress());

        ComSmartPtr<IDWriteFont> dwFont;
        hr = dwFontFamily->GetFirstMatchingFont (DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL,
                                                 dwFont.resetAndGetPointerAddress());
        jassert (dwFont != nullptr);

        const float defaultFontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (*dwFont);

        ComSmartPtr<IDWriteTextFormat> dwTextFormat;
        hr = directWriteFactory.CreateTextFormat (defaultFont.getTypefaceName().toWideCharPointer(), &fontCollection,
                                                  DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
                                                  defaultFont.getHeight() * defaultFontHeightToEmSizeFactor,
                                                  L"en-us", dwTextFormat.resetAndGetPointerAddress());

        setTextFormatProperties (text, *dwTextFormat);

        {
            DWRITE_TRIMMING trimming = { DWRITE_TRIMMING_GRANULARITY_CHARACTER, 0, 0 };
            ComSmartPtr<IDWriteInlineObject> trimmingSign;
            hr = directWriteFactory.CreateEllipsisTrimmingSign (dwTextFormat, trimmingSign.resetAndGetPointerAddress());
            hr = dwTextFormat->SetTrimming (&trimming, trimmingSign);
        }

        const int textLen = text.getText().length();

        hr = directWriteFactory.CreateTextLayout (text.getText().toWideCharPointer(), textLen, dwTextFormat,
                                                  maxWidth, maxHeight, textLayout.resetAndGetPointerAddress());

        if (FAILED (hr) || textLayout == nullptr)
            return false;

        const int numAttributes = text.getNumAttributes();

        for (int i = 0; i < numAttributes; ++i)
            addAttributedRange (*text.getAttribute (i), *textLayout, textLen, renderTarget, fontCollection);

        return true;
    }
void CtrlrLuaMethodEditorTabsLF::createTabTextLayout (const TabBarButton& button, float length, float depth, Colour colour, TextLayout& textLayout)
{
    Font font (12.0f);
    font.setUnderline (button.hasKeyboardFocus (false));

    AttributedString s;
    s.setJustification (Justification::centred);
    s.append (button.getButtonText().trim(), font, colour);

    textLayout.createLayout (s, length);
}
Ejemplo n.º 8
0
void LookAndFeel_E1::createTabTextLayout (const TabBarButton& button, float length, float depth,
                                          Colour colour, TextLayout& textLayout)
{
    Font font (depth * 0.5f);
    font.setUnderline (button.hasKeyboardFocus (false));

    AttributedString s;
    s.setJustification (Justification::centred);
    s.append (button.getButtonText().trim(), font, colour);

    textLayout.createLayout (s, length);
}
void TracktionMarketplaceUnlockForm::showBubbleMessage (const String& text, Component& target)
{
    bubble = new BubbleMessageComponent (500);
    addChildComponent (bubble);

    AttributedString attString;
    attString.append (text, Font (15.0f));

    bubble->showAt (getLocalArea (&target, target.getLocalBounds()),
                    attString, 500,  // numMillisecondsBeforeRemoving
                    true,  // removeWhenMouseClicked
                    false); // deleteSelfAfterUse
}
Ejemplo n.º 10
0
    static TextLayout layoutTooltipText (const String& text, const Colour& colour) noexcept
    {
        const float tooltipFontSize = 13.0f;
        const int maxToolTipWidth = 400;

        AttributedString s;
        s.setJustification (Justification::centred);
        s.append (text, Font (tooltipFontSize, Font::bold), colour);

        TextLayout tl;
        tl.createLayoutWithBalancedLineLengths (s, (float) maxToolTipWidth);
        return tl;
    }
Ejemplo n.º 11
0
void MainAppWindow::showMessageBubble (const String& text)
{
    currentBubbleMessage = new BubbleMessageComponent (500);
    getContentComponent()->addChildComponent (currentBubbleMessage);

    AttributedString attString;
    attString.append (text, Font (15.0f));

    currentBubbleMessage->showAt (Rectangle<int> (getLocalBounds().getCentreX(), 10, 1, 1),
                                  attString,
                                  500,  // numMillisecondsBeforeRemoving
                                  true,  // removeWhenMouseClicked
                                  false); // deleteSelfAfterUse
}
Ejemplo n.º 12
0
void CtrlrValueTreeEditorItem::paintItem (Graphics &g, int width, int height)
{
	Image icon = provider.getIconForItem (treeToEdit);
	if (isSelected())
	{
		drawSelectionRectangle (g,width,height);
	}

	g.setColour (Colours::black);

	AttributedString as = provider.getDisplayString(treeToEdit);
	as.setJustification (Justification (Justification::centredLeft));
	as.draw (g, Rectangle <float> (24.0, 0.0, width - 24.0, height));
	g.drawImageWithin (icon, 4, 0, 16, height, RectanglePlacement (RectanglePlacement::centred));
}
Ejemplo n.º 13
0
        void addTextRuns (const AttributedString& text)
        {
            Font defaultFont;
            Array<RunAttribute> runAttributes;

            {
                const int stringLength = text.getText().length();
                int rangeStart = 0;
                FontAndColour lastFontAndColour;

                // Iterate through every character in the string
                for (int i = 0; i < stringLength; ++i)
                {
                    FontAndColour newFontAndColour;
                    newFontAndColour.font = &defaultFont;

                    const int numCharacterAttributes = text.getNumAttributes();

                    for (int j = 0; j < numCharacterAttributes; ++j)
                    {
                        const AttributedString::Attribute* const attr = text.getAttribute (j);

                        // Check if the current character falls within the range of a font attribute
                        if (attr->getFont() != nullptr && (i >= attr->range.getStart()) && (i < attr->range.getEnd()))
                            newFontAndColour.font = attr->getFont();

                        // Check if the current character falls within the range of a foreground colour attribute
                        if (attr->getColour() != nullptr && (i >= attr->range.getStart()) && (i < attr->range.getEnd()))
                            newFontAndColour.colour = *attr->getColour();
                    }

                    if (i > 0 && (newFontAndColour != lastFontAndColour || i == stringLength - 1))
                    {
                        runAttributes.add (RunAttribute (lastFontAndColour,
                                                         Range<int> (rangeStart, (i < stringLength - 1) ? i : (i + 1))));
                        rangeStart = i;
                    }

                    lastFontAndColour = newFontAndColour;
                }
            }

            for (int i = 0; i < runAttributes.size(); ++i)
            {
                const RunAttribute& r = runAttributes.getReference(i);
                appendText (text, r.range, *(r.fontAndColour.font), r.fontAndColour.colour);
            }
        }
Ejemplo n.º 14
0
const AttributedString CtrlrLuaMethodEditor::getDisplayString(const ValueTree &item)	const
{
	AttributedString str;

	if (item.getType () == Ids::luaMethod)
	{
		Colour text;

		if ((bool)item.getProperty(Ids::luaMethodValid) == false)
			text = Colours::red;
		else
			text = Colours::black;

		str.append (item.getProperty(Ids::luaMethodName).toString()+"\n", Font(12.0f, Font::plain), text);

		if ((int)item.getProperty(Ids::luaMethodSource) == CtrlrLuaMethod::codeInFile)
		{
			str.append (File::descriptionOfSizeInBytes (File(item.getProperty(Ids::luaMethodSourcePath).toString()).getSize()), Font(10.0f, Font::italic), text.brighter(0.2f));
		}
		else
		{
			str.append (File::descriptionOfSizeInBytes (item.getProperty(Ids::luaMethodCode).toString().length()), Font(10.0f, Font::italic), text.brighter(0.2f));
		}

		str.setJustification (Justification::left);
	}

	if (item.getType() == Ids::luaMethodGroup)
	{
		str.append (item.getProperty(Ids::name), Font(14.0f, Font::plain), Colours::black);
		str.append (" ["+String(item.getNumChildren())+"]", Font(10.0f, Font::italic), Colours::darkgrey);

		str.setJustification (Justification::left);
	}

	if (item.getType() == Ids::luaManagerMethods)
	{
		str.append ("LUA", Font(14.0f, Font::bold), Colours::black);

		str.setJustification (Justification::left);
	}

	return (str);
}
    void setupLayout (const AttributedString& text, const float& maxWidth, const float& maxHeight,
                      ID2D1RenderTarget* const renderTarget, IDWriteFactory* const directWriteFactory,
                      IDWriteFontCollection* const fontCollection, IDWriteTextLayout** dwTextLayout)
    {
        // To add color to text, we need to create a D2D render target
        // Since we are not actually rendering to a D2D context we create a temporary GDI render target

        Font defaultFont;
        BOOL fontFound = false;
        uint32 fontIndex;
        fontCollection->FindFamilyName (defaultFont.getTypeface()->getName().toWideCharPointer(), &fontIndex, &fontFound);

        if (! fontFound)
            fontIndex = 0;

        ComSmartPtr<IDWriteFontFamily> dwFontFamily;
        HRESULT hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress());

        ComSmartPtr<IDWriteFont> dwFont;
        hr = dwFontFamily->GetFirstMatchingFont (DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL,
                                                 dwFont.resetAndGetPointerAddress());

        const float defaultFontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (dwFont);

        jassert (directWriteFactory != nullptr);

        ComSmartPtr<IDWriteTextFormat> dwTextFormat;
        hr = directWriteFactory->CreateTextFormat (defaultFont.getTypefaceName().toWideCharPointer(), fontCollection,
                                                   DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
                                                   defaultFont.getHeight() * defaultFontHeightToEmSizeFactor,
                                                   L"en-us", dwTextFormat.resetAndGetPointerAddress());

        setTextFormatProperties (text, dwTextFormat);

        const int textLen = text.getText().length();

        hr = directWriteFactory->CreateTextLayout (text.getText().toWideCharPointer(), textLen,
                                                   dwTextFormat, maxWidth, maxHeight, dwTextLayout);

        const int numAttributes = text.getNumAttributes();

        for (int i = 0; i < numAttributes; ++i)
            addAttributedRange (*text.getAttribute (i), *dwTextLayout, textLen, renderTarget, fontCollection);
    }
Ejemplo n.º 16
0
//==============================================================================
void AlertWindow::setMessage (const String& message)
{
    const String newMessage (message.substring (0, 2048));

    if (text != newMessage)
    {
        text = newMessage;

        font = getLookAndFeel().getAlertWindowMessageFont();

        AttributedString newText;
        newText.append (getName() + "\n\n", Font (font.getHeight() * 1.1f, Font::bold));
        newText.append (text, font);
        attributedText = newText;

        updateLayout (true);
        repaint();
    }
}
Ejemplo n.º 17
0
void TextLayout::createLayout (const AttributedString& text, float maxWidth)
{
    lines.clear();
    width = maxWidth;
    justification = text.getJustification();

    if (! createNativeLayout (text))
        createStandardLayout (text);

    recalculateWidth (text);
}
Ejemplo n.º 18
0
void SimpleTypeLayout::appendText (const AttributedString& text,
                                   const Range<int>& stringRange, const Font& font,
                                   const Colour& colour)
{
    String stringText = text.getText().substring(stringRange.getStart(), stringRange.getEnd());
    String::CharPointerType t (stringText.getCharPointer());
    String currentString;
    int lastCharType = 0;

    for (;;)
    {
        const juce_wchar c = t.getAndAdvance();
        if (c == 0)
            break;

        int charType;
        if (c == '\r' || c == '\n')
        {
            charType = 0;
        }
        else if (CharacterFunctions::isWhitespace (c))
        {
            charType = 2;
        }
        else
        {
            charType = 1;
        }

        if (charType == 0 || charType != lastCharType)
        {
            if (currentString.isNotEmpty())
            {
                tokens.add (new Token (currentString, font, colour,
                                       lastCharType == 2 || lastCharType == 0));
            }

            currentString = String::charToString (c);

            if (c == '\r' && *t == '\n')
                currentString += t.getAndAdvance();
        }
        else
        {
            currentString += c;
        }

        lastCharType = charType;
    }

    if (currentString.isNotEmpty())
        tokens.add (new Token (currentString, font, colour, lastCharType == 2));
}
Ejemplo n.º 19
0
void pspSystemEditorGUI::paintListBoxItem(int rowNumber, Graphics &g, int width, int height, bool rowIsSelected){
    if (rowIsSelected){
        g.fillAll (Colours::midnightblue.brighter());
    }
    
    String name;
    String type;
    String separator;
    separator = " : ";
    AttributedString a;
    a.setJustification (Justification::centredLeft);
    
    name = psManager->getSystemName(rowNumber);
    if(name == "nosystemtocall"){
        return;
    }
    type = psManager->getSystemType(rowNumber);
    

    a.append (type, Font (12.0f), Colour::greyLevel (0.7f));
    a.append(separator, Font (12.0f), Colour::greyLevel (0.7f));
    a.append (name, Font (14.0f), Colours::white.withAlpha (1.0f));
    
    a.draw (g, Rectangle<int> (width + 10, height).reduced (6, 0).toFloat());
}
void CtrlrLuaMethodCodeEditor::reportFoundMatch (CodeDocument &document, const String &methodName, const Range<int> range)
{
	CodeDocument::Position pos (document, range.getStart());
	AttributedString as;
	as.append ("Method: ", Colours::black);
	as.append (methodName, Colours::blue);

	as.append ("\tline: ", Colours::black);
	as.append (String(pos.getLineNumber()+1), Colours::darkgreen);

	as.append ("\tstart: ", Colours::black);
	as.append (String(range.getStart()), Colours::darkgreen);

	as.append ("\tend: ", Colours::black);
	as.append (String(range.getEnd()), Colours::darkgreen);

	owner.getMethodEditArea()->insertOutput (as);
}
Ejemplo n.º 21
0
void SoundboardAudioProcessorEditor::handleOscParameterMessage(OscParameter *parameter) {
    if (parameter->addressMatch("/ultraschall/soundboard/gain$")) {
        gainSlider->setValue(gainSlider->proportionOfLengthToValue(parameter->getValue()), dontSendNotification);
        AttributedString text;
        String value(gainSlider->getValue());
        if (value.length() == 1) {
            text.append("  ");
        } else if (value.length() == 2) {
            text.append(" ");
        }
        text.append(value, ThemeForeground1);
        text.append(" %", ThemeForeground1);
        gainBubble->toFront(false);
        gainBubble->showAt(gainSlider, text, 500);
        if (grid->isVisible())
            grid->resized();
    } else if(parameter->addressMatch("/ultraschall/soundboard/duck/gain$")) {
        gainSlider->setValue(gainSlider->proportionOfLengthToValue(parameter->getValue()), dontSendNotification);
    } else if(parameter->addressMatch("/ultraschall/soundboard/duck/enabled$")) {
        bool ducking = parameter->getValue();
        gainSlider->setEnabled(!ducking);
    }
}
Ejemplo n.º 22
0
AttributedString BaseTextShadowNode::getAttributedString(
  const TextAttributes &textAttributes,
  const SharedShadowNodeSharedList &childNodes
) const {
  // TODO: Implement caching.

  AttributedString attributedString;

  for (auto &&childNode : *childNodes) {
    // RawShadowNode
    SharedRawTextShadowNode rawTextShadowNode = std::dynamic_pointer_cast<const RawTextShadowNode>(childNode);
    if (rawTextShadowNode) {
      AttributedString::Fragment fragment;
      fragment.string = rawTextShadowNode->getProps()->text;
      fragment.textAttributes = textAttributes;
      attributedString.appendFragment(fragment);
      continue;
    }

    // TextShadowNode
    SharedTextShadowNode textShadowNode = std::dynamic_pointer_cast<const TextShadowNode>(childNode);
    if (textShadowNode) {
      TextAttributes localTextAttributes = textAttributes;
      localTextAttributes.apply(textShadowNode->getProps()->textAttributes);
      attributedString.appendAttributedString(textShadowNode->getAttributedString(localTextAttributes, textShadowNode->getChildren()));
      continue;
    }

    // Any other kind of ShadowNode
    AttributedString::Fragment fragment;
    fragment.shadowNode = childNode;
    fragment.textAttributes = textAttributes;
    attributedString.appendFragment(fragment);
  }

  return attributedString;
}
    void draw (CodeEditorComponent& owner, Graphics& g, const Font& fontToUse,
               const float rightClip, const float x, const int y,
               const int lineH, const float characterWidth) const
    {
        Colour lastColour (0x00000001);

        AttributedString as;
        as.setJustification (Justification::centredLeft);

        int column = 0;

        for (int i = 0; i < tokens.size(); ++i)
        {
            const float tokenX = x + column * characterWidth;
            if (tokenX > rightClip)
                break;

            const SyntaxToken& token = tokens.getReference(i);
            as.append (token.text.removeCharacters ("\r\n"), fontToUse, owner.getColourForTokenType (token.tokenType));
            column += token.length;
        }

        as.draw (g, Rectangle<float> (x, (float) y, 10000.0f, (float) lineH));
    }
    void createLayout (TextLayout& layout, const AttributedString& text, IDWriteFactory& directWriteFactory,
                       ID2D1Factory& direct2dFactory, IDWriteFontCollection& fontCollection)
    {
        // To add color to text, we need to create a D2D render target
        // Since we are not actually rendering to a D2D context we create a temporary GDI render target

        D2D1_RENDER_TARGET_PROPERTIES d2dRTProp = D2D1::RenderTargetProperties (D2D1_RENDER_TARGET_TYPE_SOFTWARE,
                                                                                D2D1::PixelFormat (DXGI_FORMAT_B8G8R8A8_UNORM,
                                                                                                   D2D1_ALPHA_MODE_IGNORE),
                                                                                0, 0,
                                                                                D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE,
                                                                                D2D1_FEATURE_LEVEL_DEFAULT);
        ComSmartPtr<ID2D1DCRenderTarget> renderTarget;
        HRESULT hr = direct2dFactory.CreateDCRenderTarget (&d2dRTProp, renderTarget.resetAndGetPointerAddress());

        ComSmartPtr<IDWriteTextLayout> dwTextLayout;

        if (! setupLayout (text, layout.getWidth(), layout.getHeight(), *renderTarget,
                           directWriteFactory, fontCollection, dwTextLayout))
            return;

        UINT32 actualLineCount = 0;
        hr = dwTextLayout->GetLineMetrics (nullptr, 0, &actualLineCount);

        layout.ensureStorageAllocated (actualLineCount);

        {
            ComSmartPtr<CustomDirectWriteTextRenderer> textRenderer (new CustomDirectWriteTextRenderer (fontCollection, text));
            hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0);
        }

        HeapBlock<DWRITE_LINE_METRICS> dwLineMetrics (actualLineCount);
        hr = dwTextLayout->GetLineMetrics (dwLineMetrics, actualLineCount, &actualLineCount);
        int lastLocation = 0;
        const int numLines = jmin ((int) actualLineCount, layout.getNumLines());
        float yAdjustment = 0;
        const float extraLineSpacing = text.getLineSpacing();

        for (int i = 0; i < numLines; ++i)
        {
            TextLayout::Line& line = layout.getLine (i);
            line.stringRange = Range<int> (lastLocation, (int) lastLocation + dwLineMetrics[i].length);
            line.lineOrigin.y += yAdjustment;
            yAdjustment += extraLineSpacing;
            lastLocation += dwLineMetrics[i].length;
        }
    }
Ejemplo n.º 25
0
    void paint (Graphics& g) override
    {
        Rectangle<float> area (getLocalBounds().toFloat().reduced (2.0f));

        g.setColour (Colours::orange);
        g.drawRoundedRectangle (area, 10.0f, 2.0f);

        AttributedString s;
        s.setJustification (Justification::centred);
        s.setWordWrap (AttributedString::none);
        s.append ("Drag Me!");
        s.setColour (Colours::white);
        s.draw (g, area);
    }
Ejemplo n.º 26
0
    void paintListBoxItem (int rowNumber, Graphics& g,
                           int width, int height, bool rowIsSelected)
    {
        if (rowIsSelected)
            g.fillAll (Colours::lightblue);

        Font font (fonts [rowNumber]);

        AttributedString s;
        s.setWordWrap (AttributedString::none);
        s.setJustification (Justification::centredLeft);
        s.append (font.getTypefaceName(), font.withPointHeight (height * 0.7f), Colours::black);
        s.append ("   " + font.getTypefaceName(), Font (height * 0.5f, Font::italic), Colours::grey);

        s.draw (g, Rectangle<int> (width, height).expanded (-4, 50).toFloat());
    }
Ejemplo n.º 27
0
    void paint (Graphics& g) override
    {
        Rectangle<float> area (getLocalBounds().toFloat().reduced (2.0f));
        g.setColour (Colours::orange.withAlpha (0.6f));
        g.fillRoundedRectangle (area, 10.0f);

        g.setColour (Colours::darkgrey);
        g.drawRoundedRectangle (area, 10.0f, 2.0f);

        AttributedString s;
        s.setJustification (Justification::centred);
        s.setWordWrap (AttributedString::none);
        s.append ("Balls!\n"
                  "(Drag Me)");
        s.setColour (Colours::black);
        s.draw (g, area);
    }
    void createLayout (TextLayout& layout, const AttributedString& text,
                       IDWriteFactory& directWriteFactory,
                       IDWriteFontCollection& fontCollection,
                       ID2D1DCRenderTarget& renderTarget)
    {
        ComSmartPtr<IDWriteTextLayout> dwTextLayout;

        if (! setupLayout (text, layout.getWidth(), layout.getHeight(), renderTarget,
                           directWriteFactory, fontCollection, dwTextLayout))
            return;

        UINT32 actualLineCount = 0;
        HRESULT hr = dwTextLayout->GetLineMetrics (nullptr, 0, &actualLineCount);

        layout.ensureStorageAllocated (actualLineCount);

        {
            ComSmartPtr<CustomDirectWriteTextRenderer> textRenderer (new CustomDirectWriteTextRenderer (fontCollection, text));
            hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0);
        }

        HeapBlock<DWRITE_LINE_METRICS> dwLineMetrics (actualLineCount);
        hr = dwTextLayout->GetLineMetrics (dwLineMetrics, actualLineCount, &actualLineCount);
        int lastLocation = 0;
        const int numLines = jmin ((int) actualLineCount, layout.getNumLines());
        float yAdjustment = 0;
        const float extraLineSpacing = text.getLineSpacing();

        for (int i = 0; i < numLines; ++i)
        {
            TextLayout::Line& line = layout.getLine (i);
            line.stringRange = Range<int> (lastLocation, (int) lastLocation + dwLineMetrics[i].length);
            line.lineOrigin.y += yAdjustment;
            yAdjustment += extraLineSpacing;
            lastLocation += dwLineMetrics[i].length;
        }
    }
Ejemplo n.º 29
0
void AlertWindow::updateLayout (const bool onlyIncreaseSize)
{
    const int titleH = 24;
    const int iconWidth = 80;

    const Font font (getLookAndFeel().getAlertWindowMessageFont());

    const int wid = jmax (font.getStringWidth (text),
                          font.getStringWidth (getName()));

    const int sw = (int) std::sqrt (font.getHeight() * wid);
    int w = jmin (300 + sw * 2, (int) (getParentWidth() * 0.7f));
    const int edgeGap = 10;
    const int labelHeight = 18;
    int iconSpace = 0;

    AttributedString attributedText;
    attributedText.append (getName(), font.withHeight (font.getHeight() * 1.1f).boldened());

    if (text.isNotEmpty())
        attributedText.append ("\n\n" + text, font);

    attributedText.setColour (findColour (textColourId));

    if (alertIconType == NoIcon)
    {
        attributedText.setJustification (Justification::centredTop);
        textLayout.createLayoutWithBalancedLineLengths (attributedText, (float) w);
    }
    else
    {
        attributedText.setJustification (Justification::topLeft);
        textLayout.createLayoutWithBalancedLineLengths (attributedText, (float) w);
        iconSpace = iconWidth;
    }

    w = jmax (350, (int) textLayout.getWidth() + iconSpace + edgeGap * 4);
    w = jmin (w, (int) (getParentWidth() * 0.7f));

    const int textLayoutH = (int) textLayout.getHeight();
    const int textBottom = 16 + titleH + textLayoutH;
    int h = textBottom;

    int buttonW = 40;
    int i;
    for (i = 0; i < buttons.size(); ++i)
        buttonW += 16 + buttons.getUnchecked(i)->getWidth();

    w = jmax (buttonW, w);

    h += (textBoxes.size() + comboBoxes.size() + progressBars.size()) * 50;

    if (buttons.size() > 0)
        h += 20 + buttons.getUnchecked(0)->getHeight();

    for (i = customComps.size(); --i >= 0;)
    {
        Component* c = customComps.getUnchecked(i);
        w = jmax (w, (c->getWidth() * 100) / 80);
        h += 10 + c->getHeight();

        if (c->getName().isNotEmpty())
            h += labelHeight;
    }

    for (i = textBlocks.size(); --i >= 0;)
    {
        const AlertTextComp* const ac = static_cast <const AlertTextComp*> (textBlocks.getUnchecked(i));
        w = jmax (w, ac->getPreferredWidth());
    }

    w = jmin (w, (int) (getParentWidth() * 0.7f));

    for (i = textBlocks.size(); --i >= 0;)
    {
        AlertTextComp* const ac = static_cast <AlertTextComp*> (textBlocks.getUnchecked(i));
        ac->updateLayout ((int) (w * 0.8f));
        h += ac->getHeight() + 10;
    }

    h = jmin (getParentHeight() - 50, h);

    if (onlyIncreaseSize)
    {
        w = jmax (w, getWidth());
        h = jmax (h, getHeight());
    }

    if (! isVisible())
    {
        centreAroundComponent (associatedComponent, w, h);
    }
    else
    {
        const int cx = getX() + getWidth() / 2;
        const int cy = getY() + getHeight() / 2;

        setBounds (cx - w / 2,
                   cy - h / 2,
                   w, h);
    }

    textArea.setBounds (edgeGap, edgeGap, w - (edgeGap * 2), h - edgeGap);

    const int spacer = 16;
    int totalWidth = -spacer;

    for (i = buttons.size(); --i >= 0;)
        totalWidth += buttons.getUnchecked(i)->getWidth() + spacer;

    int x = (w - totalWidth) / 2;
    int y = (int) (getHeight() * 0.95f);

    for (i = 0; i < buttons.size(); ++i)
    {
        TextButton* const c = buttons.getUnchecked(i);
        int ny = proportionOfHeight (0.95f) - c->getHeight();
        c->setTopLeftPosition (x, ny);
        if (ny < y)
            y = ny;

        x += c->getWidth() + spacer;

        c->toFront (false);
    }

    y = textBottom;

    for (i = 0; i < allComps.size(); ++i)
    {
        Component* const c = allComps.getUnchecked(i);
        h = 22;

        const int comboIndex = comboBoxes.indexOf (dynamic_cast <ComboBox*> (c));
        if (comboIndex >= 0 && comboBoxNames [comboIndex].isNotEmpty())
            y += labelHeight;

        const int tbIndex = textBoxes.indexOf (dynamic_cast <TextEditor*> (c));
        if (tbIndex >= 0 && textboxNames[tbIndex].isNotEmpty())
            y += labelHeight;

        if (customComps.contains (c))
        {
            if (c->getName().isNotEmpty())
                y += labelHeight;

            c->setTopLeftPosition (proportionOfWidth (0.1f), y);
            h = c->getHeight();
        }
        else if (textBlocks.contains (c))
        {
            c->setTopLeftPosition ((getWidth() - c->getWidth()) / 2, y);
            h = c->getHeight();
        }
        else
        {
            c->setBounds (proportionOfWidth (0.1f), y, proportionOfWidth (0.8f), h);
        }

        y += h + 10;
    }

    setWantsKeyboardFocus (getNumChildComponents() == 0);
}
Ejemplo n.º 30
0
void SimpleTypeLayout::getGlyphLayout (const AttributedString& text, GlyphLayout& glyphLayout)
{
    clear();
    int stringLength = text.getText().length();
    int numCharacterAttributes = text.getCharAttributesSize();
    int rangeStart = 0;
    // Character attributes are applied as a series of ranges. These ranges may overlap or there may
    // be multiple attributes for the same range. We need to come up with a single set of unique and
    // non overlapping ranges.
    // The approach below iterates through every character, looks through all the attributes and their
    // ranges and stores the last font or color that was applied. It think constructs a set of unique
    // and non overlapping ranges by comparing each character's attributes to the previous characters
    // attributes.
    // A more efficient approach may be to split and combine the individual ranges to construct the
    // set of unique and non overlapping ranges. This more efficient approach, if possible, would only
    // need to iterate through all the attributes once. This would be much faster than the current
    // approach which loops through all the attributes for every character.
    Font defaultFont;
    Colour defaultColour (Colours::black);
    Array<RunAttribute> runAttributes;
    Array<CharAttribute> charAttributes;
    charAttributes.ensureStorageAllocated (stringLength);
    // Iterate through every character in the string
    for (int i = 0; i < stringLength; ++i)
    {
        CharAttribute attribute;
        attribute.font = &defaultFont;
        attribute.colour = &defaultColour;
        // Iterate through every character attribute
        for (int j = 0; j < numCharacterAttributes; ++j)
        {
            Attr* attr = text.getCharAttribute (j);
            // Check if the current character falls within the range of a font attribute
            if (attr->attribute == Attr::font && (i >= attr->range.getStart()) && (i < attr->range.getEnd()))
            {
                AttrFont* attrFont = static_cast<AttrFont*>(attr);
                attribute.font = &(attrFont->font);
            }
            // Check if the current character falls within the range of a foreground colour attribute
            if (attr->attribute == Attr::foregroundColour && (i >= attr->range.getStart()) && (i < attr->range.getEnd()))
            {
                AttrColour* attrColour = static_cast<AttrColour*>(attr);
                attribute.colour = &(attrColour->colour);
            }
        }
        charAttributes.add(attribute);
        // Skip the first character since we are comparing to previous characters
        if (i == 0)
            continue;
        if ((charAttributes[i-1].font != charAttributes[i].font) ||
            (charAttributes[i-1].colour != charAttributes[i].colour) ||
            (*(charAttributes[i-1].font) != *(charAttributes[i].font)) ||
            (*(charAttributes[i-1].colour) != *(charAttributes[i].colour)) ||
            (i + 1 == stringLength))
        {
            // The current character has a new font or new color or there is no next character
            RunAttribute attribute;
            attribute.range.setStart (rangeStart);
            attribute.range.setEnd (i);
            if (i + 1 == stringLength)
                attribute.range.setEnd (i+1);
            attribute.font = charAttributes[i-1].font;
            attribute.colour = charAttributes[i-1].colour;
            runAttributes.add (attribute);
            rangeStart = i;
        }

    }
    charAttributes.clear();
    for (int i = 0; i < runAttributes.size(); ++i)
    {
        appendText (text, runAttributes[i].range, *(runAttributes[i].font), *(runAttributes[i].colour));
    }
    runAttributes.clear();
    // Run layout to break strings into words and create lines from words
    layout ((int) glyphLayout.getWidth());
    // Use tokens to create Glyph Structures
    glyphLayout.setNumLines (getNumLines());
    // Set Starting Positions to 0
    int charPosition = 0;
    int lineStartPosition = 0;
    int runStartPosition = 0;
    // Create first GlyphLine and GlyphRun
    GlyphLine* glyphLine = new GlyphLine();
    GlyphRun* glyphRun = new GlyphRun();
    for (int i = 0; i < tokens.size(); ++i)
    {
        const Token* const t = tokens.getUnchecked (i);
        // See TextLayout::draw
        const float xOffset = (float) t->x;
        const float yOffset = (float) t->y;
        // See GlyphArrangement::addCurtailedLineOfText
        Array <int> newGlyphs;
        Array <float> xOffsets;
        t->font.getGlyphPositions (t->text.trimEnd(), newGlyphs, xOffsets);
        // Resize glyph run array
        glyphRun->setNumGlyphs (glyphRun->getNumGlyphs() + newGlyphs.size());
        // Add each glyph in the token to the current GlyphRun
        for (int j = 0; j < newGlyphs.size(); ++j)
        {
            const float thisX = xOffsets.getUnchecked (j);
            // Check if this is the first character in the line
            if (charPosition == lineStartPosition)
            {
                // Save line offset data
                Point<float> origin (xOffset, yOffset + t->font.getAscent());
                glyphLine->setLineOrigin (origin);
            }
            float xPos = glyphLayout.getX() + glyphLine->getLineOrigin().getX() + xOffset + thisX;
            float yPos = glyphLayout.getY() + glyphLine->getLineOrigin().getY();
            Glyph* glyph = new Glyph (newGlyphs.getUnchecked(j), xPos, yPos);
            glyphRun->addGlyph (glyph);
            charPosition++;
        }
        if (t->isWhitespace || t->isNewLine)
            ++charPosition;
        // We have reached the end of a token, we may need to create a new run or line
        if (i + 1 == tokens.size())
        {
            // We have reached the last token
            // Close GlyphRun
            Range<int> runRange (runStartPosition, charPosition);
            glyphRun->setStringRange (runRange);
            glyphRun->setFont (t->font);
            glyphRun->setColour (t->colour);
            // Check if run descent is the largest in the line
            if (t->font.getDescent() > glyphLine->getDescent())
                glyphLine->setDescent (t->font.getDescent());
            glyphLine->addGlyphRun (glyphRun);
            // Close GlyphLine
            Range<int> lineRange (lineStartPosition, charPosition);
            glyphLine->setStringRange (lineRange);
            glyphLayout.addGlyphLine (glyphLine);
        }
        else
        {
            // We have not yet reached the last token
            const Token* const nextt = tokens.getUnchecked (i+1);
            if (t->font != nextt->font || t->colour != nextt->colour)
            {
                //The next token has a new font or new colour
                // Close GlyphRun
                Range<int> runRange (runStartPosition, charPosition);
                glyphRun->setStringRange (runRange);
                glyphRun->setFont (t->font);
                glyphRun->setColour (t->colour);
                // Check if run descent is the largest in the line
                if (t->font.getDescent() > glyphLine->getDescent())
                    glyphLine->setDescent (t->font.getDescent());
                glyphLine->addGlyphRun (glyphRun);
                // Create the next GlyphRun
                runStartPosition = charPosition;
                glyphRun = new GlyphRun();
            }
            if (t->line != nextt->line)
            {
                // The next token is in a new line
                // Close GlyphRun
                Range<int> runRange (runStartPosition, charPosition);
                glyphRun->setStringRange (runRange);
                glyphRun->setFont (t->font);
                glyphRun->setColour (t->colour);
                // Check if run descent is the largest in the line
                if (t->font.getDescent() > glyphLine->getDescent())
                    glyphLine->setDescent (t->font.getDescent());
                glyphLine->addGlyphRun (glyphRun);
                // Close GlyphLine
                Range<int> lineRange (lineStartPosition, charPosition);
                glyphLine->setStringRange (lineRange);
                glyphLayout.addGlyphLine (glyphLine);
                // Create the next GlyphLine and GlyphRun
                runStartPosition = charPosition;
                lineStartPosition = charPosition;
                glyphLine = new GlyphLine();
                glyphRun = new GlyphRun();
            }
        }
    }
    // Apply Layout Text Alignment
    if (text.getTextAlignment() == AttributedString::right ||
        text.getTextAlignment() == AttributedString::center)
    {
        int totalW = (int) glyphLayout.getWidth();
        for (int i = 0; i < getNumLines(); ++i)
        {
            const int lineW = getLineWidth (i);
            int dx = 0;
            if (text.getTextAlignment() == AttributedString::right)
            {
                dx = totalW - lineW;
            }
            else if (text.getTextAlignment() == AttributedString::center)
            {
                dx = (totalW - lineW) / 2;
            }
            GlyphLine& glyphLine = glyphLayout.getGlyphLine (i);
            Point<float> lineOrigin = glyphLine.getLineOrigin();
            lineOrigin.setX (lineOrigin.getX() + dx);
            glyphLine.setLineOrigin (lineOrigin);
        }
    }
}