package com.beardedhen.androidbootstrap; import android.content.Context; import com.beardedhen.androidbootstrap.font.FontAwesome; import com.beardedhen.androidbootstrap.font.IconSet; import com.beardedhen.androidbootstrap.font.MaterialIcons; import com.beardedhen.androidbootstrap.font.Typicon; import static com.beardedhen.androidbootstrap.TypefaceProvider.getRegisteredIconSets; import static com.beardedhen.androidbootstrap.TypefaceProvider.retrieveRegisteredIconSet; /** * Resolves markdown strings using FA codes and produces BootstrapText instances. */ class IconResolver { private static final String REGEX_FONT_AWESOME = "(fa_|fa-)[a-z_0-9]+"; private static final String REGEX_TYPICONS = "(ty_|ty-)[a-z_0-9]+"; private static final String REGEX_MATERIAL_ICONS = "(md_)[a-z_0-9]+"; /** * Resolves markdown to produce a BootstrapText instance. e.g. "{fa_android}" would be replaced * with the appropriate FontAwesome character and a SpannableString producec. * * @param context the current context * @param markdown the markdown string * @param editMode - whether the view requesting the icon set is displayed in the preview editor * @return a constructed BootstrapText */ static BootstrapText resolveMarkdown(Context context, String markdown, boolean editMode) { if (markdown == null) { return null; } else { // detect {fa_*} and split into spannable, ignore escaped chars BootstrapText.Builder builder = new BootstrapText.Builder(context, editMode); int lastAddedIndex = 0; int startIndex = -1; int endIndex = -1; for (int i = 0; i < markdown.length(); i++) { char c = markdown.charAt(i); if (c == '\\') { // escape sequence, ignore next char i += 2; continue; } if (c == '{') { startIndex = i; } else if (c == '}') { endIndex = i; } if (startIndex != -1 && endIndex != -1) { // recognised markdown string if (startIndex >= 0 && endIndex < markdown.length()) { String iconCode = markdown.substring(startIndex + 1, endIndex).replaceAll("\\-", "_"); builder.addText(markdown.substring(lastAddedIndex, startIndex)); if (iconCode.matches(REGEX_FONT_AWESOME)) { // text is FontAwesome code if (editMode) { builder.addText("?"); } else { builder.addIcon(iconCode, retrieveRegisteredIconSet(FontAwesome.FONT_PATH, false)); } } else if (iconCode.matches(REGEX_TYPICONS)) { if (editMode) { builder.addText("?"); } else { builder.addIcon(iconCode, retrieveRegisteredIconSet(Typicon.FONT_PATH, false)); } } else if(iconCode.matches(REGEX_MATERIAL_ICONS)){ if (editMode) { builder.addText("?"); } else { builder.addIcon(iconCode, retrieveRegisteredIconSet(MaterialIcons.FONT_PATH, false)); } } else { if (editMode) { builder.addText("?"); } else { builder.addIcon(iconCode, resolveIconSet(iconCode)); } } lastAddedIndex = endIndex + 1; } startIndex = -1; endIndex = -1; } } return builder.addText(markdown.substring(lastAddedIndex, markdown.length())).build(); } } /** * Searches for the unicode character value for the Font Icon Code. This method searches all * active FontIcons in the application. * * @param iconCode the font icon code * @return the unicode character matching the icon, or null if none matches */ private static IconSet resolveIconSet(String iconCode) { CharSequence unicode; for (IconSet set : getRegisteredIconSets()) { if (set.fontPath().equals(FontAwesome.FONT_PATH) || set.fontPath().equals(Typicon.FONT_PATH) || set.fontPath().equals(MaterialIcons.FONT_PATH)) { continue; // already checked previously, ignore } unicode = set.unicodeForKey(iconCode); if (unicode != null) { return set; } } String message = String.format("Could not find FontIcon value for '%s', " + "please ensure that it is mapped to a valid font", iconCode); throw new IllegalArgumentException(message); } }