void TreeItem::draw(ExpandTree* tree, AlloyContext* context, const pixel2& offset) { box2px bounds = getBounds(); NVGcontext* nvg = context->nvgContext; nvgFontFaceId(nvg, context->getFontHandle(FontType::Icon)); float spaceWidth = fontSize + PADDING * 2; float iconWidth = 0; static const std::string rightArrow = CodePointToUTF8(0xf0da); static const std::string downArrow = CodePointToUTF8(0xf0d7); pixel2 pt = bounds.position + offset; bool selected = (tree->getSelectedItem() == this)&&!tree->isOverArrow(); nvgFontSize(nvg, fontSize); if (iconCodeString.length() > 0) { iconWidth = nvgTextBounds(nvg, 0, 0, iconCodeString.c_str(), nullptr, nullptr) + PADDING * 2; if (children.size() > 0 || onExpand) { nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_TOP); if (tree->isOverArrow()) { nvgFillColor(nvg, context->theme.LIGHTEST); } else { nvgFillColor(nvg, context->theme.LIGHTER); } nvgText(nvg, pt.x + spaceWidth * 0.5f, pt.y + PADDING, (expanded) ? downArrow.c_str() : rightArrow.c_str(), nullptr); } if (selected) { nvgFillColor(nvg, context->theme.LIGHTEST); } else { nvgFillColor(nvg, context->theme.LIGHTER); } nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); nvgText(nvg, pt.x + spaceWidth, pt.y + PADDING, iconCodeString.c_str(), nullptr); } if (name.length() > 0) { if (selected) { nvgFillColor(nvg, context->theme.LIGHTEST); } else { nvgFillColor(nvg, context->theme.LIGHTER); } nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); nvgText(nvg, pt.x + iconWidth + spaceWidth, pt.y + PADDING, name.c_str(), nullptr); } if (expanded) { for (TreeItemPtr& item : children) { item->draw(tree, context, offset); } } }
AwesomeGlyph::AwesomeGlyph(int codePoint, AlloyContext* context, const FontStyle& style, pixel height) : Glyph(CodePointToUTF8(codePoint), GlyphType::Awesome, 0, height), codePoint( codePoint), style(style) { NVGcontext* nvg = context->nvgContext; nvgFontSize(nvg, height); nvgFontFaceId(nvg, context->getFontHandle(FontType::Icon)); width = nvgTextBounds(nvg, 0, 0, name.c_str(), nullptr, nullptr); }
static void ApplyQuotes ( XMP_VarString * item, UniCodePoint openQuote, UniCodePoint closeQuote, bool allowCommas ) { bool prevSpace = false; size_t charOffset, charLen; UniCharKind charKind; UniCodePoint uniChar; // ----------------------------------------------------------------------------------------- // See if there are any separators in the value. Stop at the first occurrance. This is a bit // tricky in order to make typical typing work conveniently. The purpose of applying quotes // is to preserve the values when splitting them back apart. That is CatenateContainerItems // and SeparateContainerItems must round trip properly. For the most part we only look for // separators here. Internal quotes, as in -- Irving "Bud" Jones -- won't cause problems in // the separation. An initial quote will though, it will make the value look quoted. charOffset = 0; ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar ); if ( charKind != UCK_quote ) { for ( charOffset = 0; size_t(charOffset) < item->size(); charOffset += charLen ) { ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar ); if ( charKind == UCK_space ) { if ( prevSpace ) break; // Multiple spaces are a separator. prevSpace = true; } else { prevSpace = false; if ( (charKind == UCK_semicolon) || (charKind == UCK_control) ) break; if ( (charKind == UCK_comma) && (! allowCommas) ) break; } } } if ( size_t(charOffset) < item->size() ) { // -------------------------------------------------------------------------------------- // Create a quoted copy, doubling any internal quotes that match the outer ones. Internal // quotes did not stop the "needs quoting" search, but they do need doubling. So we have // to rescan the front of the string for quotes. Handle the special case of U+301D being // closed by either U+301E or U+301F. XMP_VarString newItem; size_t splitPoint; for ( splitPoint = 0; splitPoint <= charOffset; ++splitPoint ) { ClassifyCharacter ( item->c_str(), splitPoint, &charKind, &charLen, &uniChar ); if ( charKind == UCK_quote ) break; } CodePointToUTF8 ( openQuote, newItem ); newItem.append ( *item, 0, splitPoint ); // Copy the leading "normal" portion. for ( charOffset = splitPoint; size_t(charOffset) < item->size(); charOffset += charLen ) { ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar ); newItem.append ( *item, charOffset, charLen ); if ( (charKind == UCK_quote) && IsSurroundingQuote ( uniChar, openQuote, closeQuote ) ) { newItem.append ( *item, charOffset, charLen ); } } XMP_VarString closeStr; CodePointToUTF8 ( closeQuote, closeStr ); newItem.append ( closeStr ); *item = newItem; } } // ApplyQuotes
TreeItem::TreeItem(const std::string& name, int iconCode, float fontSize) : name(name), fontSize(fontSize),spaceWidth(0.0f), expanded(name.length() == 0) { if (iconCode != 0) { iconCodeString = CodePointToUTF8(iconCode); } }