@Override
    public void render(final Context context, final T value, final SafeHtmlBuilder sb) {
        if (value == null) {
            sb.append(SafeHtmlUtils.EMPTY_SAFE_HTML);
        } else {
            String cellText = null;
            if (cellTextExtractor != null) {
                cellText = cellTextExtractor.apply(value);
            }

            final List<Item> menuItems = NullSafe.get(menuCreator, mc -> mc.apply(value));
            if (NullSafe.hasItems(menuItems)) {
                final SafeHtml textSafeHtml = template
                        .div("commandLinkText", SafeHtmlUtils.fromString(cellText));

                sb.appendHtmlConstant("<div class=\"commandLinkContainer\">");
                sb.append(textSafeHtml);

                final SafeHtml icon = SvgImageUtil.toSafeHtml(
                        ICON_IMAGE,
                        ICON_CLASS_NAME,
                        HOVER_ACTION_MENU_CLASS_NAME);

                if (menuItems.size() == 1 &&
                    menuItems.get(0) instanceof final MenuItem menuItem &&
                    menuItem.getCommand() != null) {
                    // Single item with a command so no menu popup needed
                    final SafeHtml tooltip = NullSafe.getOrElse(menuItem, MenuItem::getTooltip, menuItem.getText());
                    sb.append(template.divWithTitle(tooltip.asString(), icon));
                } else {
                    // Build the menu popup
                    sb.append(template.divWithTitle("Actions...", icon));
                }

                sb.appendHtmlConstant("</div>");
            } else {
                // No menu items so just show the text
                if (NullSafe.isBlankString(cellText)) {
                    sb.append(SafeHtmlUtils.EMPTY_SAFE_HTML);
                } else {
                    sb.append(SafeHtmlUtils.fromString(cellText));
                }
            }
        }
    }
@param cellTextExtractor Function to supply the text value of the cell
@param menuCreator       A function to create a list of menu items to show when the hover
                         icon is clicked. If the list contains only one item and that item
                         is an instance of {@link stroom.widget.menu.client.presenter.MenuItem}
                         and has a command, then clicking the hover icon will fire the command
                         without showing the menu.
stroom-core-client-widget/src/main/java/stroom/cell/info/client/HoverActionMenuCell.java