CB_UI_Base.GL_UI.Controls.html.HtmlView.java Source code

Java tutorial

Introduction

Here is the source code for CB_UI_Base.GL_UI.Controls.html.HtmlView.java

Source

/* 
 * Copyright (C) 2015 team-cachebox.de
 *
 * Licensed under the : GNU General Public License (GPL);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.gnu.org/licenses/gpl.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package CB_UI_Base.GL_UI.Controls.html;

import java.util.List;

import org.slf4j.LoggerFactory;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.utils.Align;

import CB_Translation_Base.TranslationEngine.Translation;
import CB_UI_Base.Enums.WrapType;
import CB_UI_Base.GL_UI.CB_View_Base;
import CB_UI_Base.GL_UI.GL_View_Base;
import CB_UI_Base.GL_UI.IRunOnGL;
import CB_UI_Base.GL_UI.Controls.Box;
import CB_UI_Base.GL_UI.Controls.EditTextField;
import CB_UI_Base.GL_UI.Controls.Image;
import CB_UI_Base.GL_UI.Controls.ImageButton;
import CB_UI_Base.GL_UI.Controls.ImageLoader;
import CB_UI_Base.GL_UI.Controls.LinkLabel;
import CB_UI_Base.GL_UI.Controls.ScrollBox;
import CB_UI_Base.GL_UI.Controls.List.ListViewBase.IListPosChanged;
import CB_UI_Base.GL_UI.Controls.List.ListViewItemBase;
import CB_UI_Base.GL_UI.Controls.List.Scrollbar;
import CB_UI_Base.GL_UI.Controls.List.V_ListView;
import CB_UI_Base.GL_UI.Controls.MessageBox.GL_MsgBox;
import CB_UI_Base.GL_UI.GL_Listener.GL;
import CB_UI_Base.GL_UI.utils.ColorDrawable;
import CB_UI_Base.Math.CB_RectF;
import CB_UI_Base.Math.UI_Size_Base;
import CB_UI_Base.graphics.FontCache;
import CB_UI_Base.settings.CB_UI_Base_Settings;
import CB_Utils.Lists.CB_List;
import CB_Utils.Log.Log;
import CB_Utils.Log.Trace;
import CB_Utils.Util.HSV_Color;
import net.htmlparser.jericho.Source;

/**
 * @author Longri
 */
public class HtmlView extends ScrollBox implements ListLayout {

    private boolean textOnly = false;
    private EditTextField textOnlyField;

    final static org.slf4j.Logger log = LoggerFactory.getLogger(HtmlView.class);
    static int margin;
    private Box contentBox;
    private List<Html_Segment> segmentList;
    private CB_List<CB_View_Base> segmentViewList;

    public HtmlView(CB_RectF rec) {
        super(rec);
        margin = UI_Size_Base.that.getMargin() / 2;
        this.setClickable(true);
    }

    public void showHtml(final String html) throws Exception {
        clearHtml();
        if (textOnly) {

            String htmlSource = html.replace("</p>", "</p><br>");
            Source source = new Source(htmlSource);

            StringBuilder sb = new StringBuilder();

            source.getRenderer().appendTo(sb);

            String text = sb.toString();

            textOnlyField = new EditTextField(this, this, null, this.name + " textOnlyField", WrapType.WRAPPED);
            textOnlyField.dontShowSoftKeyBoardOnFocus();
            textOnlyField.setNoBorders();
            textOnlyField.setText(text);
            textOnlyField.setEditable(false);
            textOnlyField.showFromLineNo(0);

            this.addChildDirekt(textOnlyField);

            this.setVirtualHeight(this.getHeight());
            this.scrollTo(0);

            // this.setUndragable();
            this.setDragable();

        } else {
            this.setDragable();

            if (textOnlyField != null) {
                this.removeChildsDirekt(textOnlyField);
                textOnlyField = null;
            }

            if (segmentList != null) {
                segmentList.clear();
            }
            segmentViewList = new CB_List<CB_View_Base>();
            Exception any = null;

            try {
                Source source = new CB_FormatedHtmlSource(html);
                segmentList = new CB_Html_Renderer(source).getElementList();

                addViewsToBox(segmentList, segmentViewList, this.getWidth() /** 2*/
                        , this);
            } catch (Exception e) {
                any = e;
            }
            layout(segmentViewList);
            if (any != null)
                throw any;
        }

    }

    static int test = 0;

    // TODO Calculate innerWidth to max line width! HtmlView can scroll
    // horizontal
    public static void addViewsToBox(List<Html_Segment> segmentList, CB_List<CB_View_Base> segmentViewList,
            float innerWidth, final ListLayout relayout) {
        for (int i = 0, n = segmentList.size(); i < n; i++) {
            Html_Segment seg = segmentList.get(i);

            switch (seg.segmentTyp) {
            case HR:
                addHR(segmentViewList, (Html_Segment_HR) seg, innerWidth);
                break;
            case Image:
                addImage(segmentViewList, seg, relayout, innerWidth);
                break;
            case TextBlock:
                addTextBlog(segmentViewList, (Html_Segment_TextBlock) seg, innerWidth - margin);
                break;
            case List:
                addListBlog(segmentViewList, (HTML_Segment_List) seg, innerWidth - margin);
                break;
            case Input:
                addInput(segmentViewList, (Html_Segment_Input) seg, relayout, innerWidth);
                break;
            case Table:
                addTableBlog(segmentViewList, (HTML_Segment_Table) seg, innerWidth);
                break;
            default:
                break;

            }
        }
    }

    private static float addInput(final CB_List<CB_View_Base> segmentViewList, final Html_Segment_Input seg,
            final ListLayout relayout, float innerWidth) {

        if (!seg.value.startsWith("att_"))
            return 0;

        ImageLoader img = new ImageLoader();
        img.setImage(seg.imagePath);

        ImageButton imgBtn = new ImageButton(img) {

            @Override
            public void onResized(CB_RectF rec) {
                super.onResized(rec);
                this.setWidth(this.getHeight());
                GL.that.RunOnGL(new IRunOnGL() {

                    @Override
                    public void run() {
                        relayout.layout(segmentViewList);
                    }
                });
            }
        };
        imgBtn.setWidth(imgBtn.getHeight());

        imgBtn.setOnClickListener(new OnClickListener() {

            @Override
            public boolean onClick(GL_View_Base v, int x, int y, int pointer, int button) {
                GL_MsgBox.Show(Translation.Get(seg.value));
                return true;
            }
        });

        segmentViewList.add(imgBtn);
        return imgBtn.getHeight();
    }

    private static float addListBlog(CB_List<CB_View_Base> segmentViewList, HTML_Segment_List seg,
            float innerWidth) {
        Html_ListView ListcontentBox = new Html_ListView(innerWidth, seg);
        segmentViewList.add(ListcontentBox);
        return ListcontentBox.getHeight();
    }

    private static float addTableBlog(CB_List<CB_View_Base> segmentViewList, HTML_Segment_Table seg,
            float innerWidth) {
        Html_TableView TableContentBox = new Html_TableView(innerWidth, seg);
        segmentViewList.add(TableContentBox);
        return TableContentBox.getHeight();
    }

    @Override
    public void layout(CB_List<CB_View_Base> segmentViewList) {

        if (contentBox != null)
            contentBox.removeChildsDirekt();

        contentBox = addViewsToContentBox(this, segmentViewList);
        this.addChild(contentBox);
        this.setVirtualHeight(contentBox.getHeight());
        this.scrollTo(0);
    }

    static Box addViewsToContentBox(CB_View_Base parent, CB_List<CB_View_Base> segmentViewList) {
        Box content = new Box(parent, "topContent");

        int testcount = 0;

        Log.debug(log, "HTML View Layout");
        Log.debug(log, "   " + Trace.getCallerName(0));
        Log.debug(log, "   " + Trace.getCallerName(1));
        Log.debug(log, "   " + Trace.getCallerName(2));

        float innerWidth = parent.getInnerWidth() - (margin * 2);
        int maxAttributeButtonsPerLine = (int) (innerWidth / (UI_Size_Base.that.getButtonHeight()));
        float contentHeight = 0;
        int attLines = 1;
        for (int i = 0, n = segmentViewList.size(); i < n; i++) {

            CB_View_Base view = segmentViewList.get(i);

            if (view instanceof ImageButton) {
                if (testcount++ > maxAttributeButtonsPerLine) {
                    attLines++;
                    testcount = 0;
                }
            } else {
                contentHeight += view.getHeight();
            }
        }

        contentHeight += (attLines * UI_Size_Base.that.getButtonHeight());

        content.setWidth(innerWidth);
        content.setClickable(true);
        content.setHeight(contentHeight);
        content.setZeroPos();
        content.setX(margin);

        content.setMargins(0, 0);
        content.initRow();
        testcount = 0;

        float maxWidth = 0;

        for (int i = 0, n = segmentViewList.size(); i < n; i++) {

            CB_View_Base view = segmentViewList.get(i);

            view.measureRec();
            maxWidth = Math.max(maxWidth, view.getWidth());
            if (view instanceof Image) {
                content.addLast(segmentViewList.get(i));
            } else if (view instanceof ImageButton) {
                if (testcount++ > maxAttributeButtonsPerLine) {
                    content.addLast(segmentViewList.get(i), FIXED);
                    testcount = 0;
                } else {
                    content.addNext(segmentViewList.get(i), FIXED);
                }

            } else {
                content.addLast(segmentViewList.get(i), FIXED);
            }

        }

        content.setWidth(maxWidth);

        for (int i = 0, n = content.getchilds().size(); i < n; i++) {

            GL_View_Base child = content.getChild(i);
            if (child instanceof Html_ListView) {
                // move tab on x
                float tabX = content.getWidth() - ((Html_ListView) child).getContentWidth();
                child.setX(tabX);
                // child.setX(0);
            }

        }
        return content;
    }

    private static float addHR(CB_List<CB_View_Base> segmentViewList, Html_Segment_HR seg, float innerWidth) {

        HrView hrView = new HrView(0, 0, innerWidth, seg.hrsize, "hr");

        hrView.setBackground(new ColorDrawable((HSV_Color) getColor(seg.getColor())));

        segmentViewList.add(hrView);
        return hrView.getHeight();
    }

    private static float lastRelayoutStateTime = 0;

    private static float addImage(final CB_List<CB_View_Base> segmentViewList, Html_Segment seg,
            final ListLayout relayout, float innerWidth) {
        Image img = new Image(0, 0, innerWidth, 50, "Html-Image", true) {

            @Override
            public void onResized(CB_RectF rec) {
                super.onResized(rec);
                GL.that.RunOnGL(new IRunOnGL() {

                    @Override
                    public void run() {
                        if (lastRelayoutStateTime == GL.that.getStateTime())
                            return;
                        lastRelayoutStateTime = GL.that.getStateTime();
                        relayout.layout(segmentViewList);
                    }
                });
            }
        };
        img.setHAlignment(seg.hAlignment);
        img.setImageURL(seg.formatedText);

        img.forceImageLoad();

        segmentViewList.add(img);
        return img.getHeight();
    }

    private static float addTextBlog(CB_List<CB_View_Base> segmentViewList, Html_Segment_TextBlock seg,
            float innerWidth) {

        boolean markUp = !seg.hyperLinkList.isEmpty();

        BitmapFont font = FontCache.get(markUp, seg.getFontFamily(), seg.getFontStyle(), seg.getFontSize());
        GlyphLayout layout = new GlyphLayout(); // dont do this every frame!
        // Store it as member
        layout.setText(font, seg.formatedText, getColor(Color.BLACK), innerWidth - (margin * 2), Align.left, true);

        float segHeight = layout.height + (margin * 2);

        parseHyperLinks(seg, "http://");
        parseHyperLinks(seg, "www.");

        LinkLabel lbl = new LinkLabel("HtmlView" + " lbl", 0, 0, innerWidth - (margin * 2), segHeight);

        if (markUp) {
            lbl.setMarkupEnabled(true);
        }

        lbl.setTextColor(getColor(seg.getFontColor()));
        lbl.setFont(font).setHAlignment(seg.hAlignment);

        if (markUp) {
            lbl.addHyperlinks(seg.hyperLinkList);
        }

        lbl.setWrappedText(seg.formatedText);
        lbl.setUnderline(seg.underline);
        lbl.setStrikeout(seg.strikeOut);
        segmentViewList.add(lbl);

        return lbl.getHeight();
    }

    private static Color getColor(Color color) {
        if (CB_UI_Base_Settings.nightMode.getValue())
            color = HSV_Color.colorMatrixManipulation(color, HSV_Color.NIGHT_COLOR_MATRIX);
        return color;
    }

    private static void parseHyperLinks(Html_Segment_TextBlock seg, String hyperLinkTag) {
        try {
            if (seg.formatedText.contains(hyperLinkTag)) {
                // add to hyperLings

                int start = seg.formatedText.indexOf(hyperLinkTag);

                int end1 = seg.formatedText.indexOf(" ", start);
                int end2 = seg.formatedText.indexOf("\r", start);
                int end3 = seg.formatedText.indexOf("\n", start);

                if (end1 < 0)
                    end1 = Integer.MAX_VALUE;
                if (end2 < 0)
                    end2 = Integer.MAX_VALUE;
                if (end3 < 0)
                    end3 = Integer.MAX_VALUE;

                int end = Math.min(Math.min(end1, end2), end3);

                if (end == Integer.MAX_VALUE) {
                    end = seg.formatedText.length();
                }

                String link = seg.formatedText.substring(start, end);

                if (link.endsWith(")") || link.endsWith("]") || link.endsWith("}")) {
                    link = seg.formatedText.substring(start, end - 1);
                }

                HyperLinkText hyper = new HyperLinkText(link.trim(), link.trim());
                seg.hyperLinkList.add(hyper);
            }
        } catch (Exception e) {
            Log.err(log, "parseHyperLinks", e);
        }
    }

    @Override
    public void dispose() {
        clearHtml();
        super.dispose();
    }

    private void clearHtml() {

        if (contentBox == null)
            return;

        synchronized (contentBox) {
            Log.debug(log, "Clear html");
            this.removeChilds();
            if (segmentViewList != null) {
                for (CB_View_Base view : segmentViewList) {
                    if (view != null) {
                        view.dispose();
                    }
                    view = null;
                }
                segmentViewList.clear();
            }

            if (segmentList != null) {
                for (Html_Segment segment : segmentList) {
                    if (segment != null) {
                        segment.dispose();
                    }
                    segment = null;
                }
                segmentList.clear();
            }

            if (contentBox != null) {
                for (GL_View_Base view : contentBox.getchilds()) {
                    if (view != null) {
                        view.dispose();
                    }
                    view = null;
                }
                contentBox.dispose();
                contentBox = null;
            }
        }
    }

    /**
     * Return true, if this in text only mode!
     * 
     * @return
     */
    public boolean getTextOnly() {
        return textOnly;
    }

    public void setTextOnly(boolean value) {
        textOnly = value;
    }

    private int touchXPos;
    private float lastContentXPos;

    @Override
    public boolean onTouchDown(int x, int y, int pointer, int button) {
        touchXPos = x;
        lastContentXPos = contentBox.getX();
        return true; // muss behandelt werden, da sonnst kein onTouchDragged()
        // ausgelsst wird.
    }

    @Override
    public boolean onTouchDragged(int x, int y, int pointer, boolean KineticPan) {
        int draged = x - touchXPos;
        contentBox.setX(lastContentXPos + draged);

        if (contentBox.getX() > margin)
            contentBox.setX(margin);
        else if (contentBox.getMaxX() < this.innerWidth)
            contentBox.setX(this.innerWidth - contentBox.getWidth());

        return true;
    }

    @Override
    protected void initScrollBox() {
        // todo: check to have no scroll(? - margin) oder rec.getHalfHeight()
        virtualHeight = this.getHeight();

        // Override onTouDown from ListView and return false for consume
        // onTouchDown Event on HtmlView!
        lv = new V_ListView(this, this, "ListView-" + name) {
            @Override
            public boolean onTouchDown(int x, int y, int pointer, int button) {
                super.onTouchDown(x, y, pointer, button);
                return false;
            }
        };
        lv.setClickable(true);

        item = new ListViewItemBase(this, 0, "ListViewItem-" + name) {

            @Override
            protected void SkinIsChanged() {
            }

            @Override
            protected void Initial() {
                isInitial = true;
            }

        };

        item.setHeight(virtualHeight);
        item.setClickable(true);
        thisAdapter = new CustomAdapter();
        lv.setDisposeFlag(false);
        lv.setBaseAdapter(thisAdapter);
        Layout();

        final Scrollbar scrollBar = new Scrollbar(lv);
        lv.addListPosChangedEventHandler(new IListPosChanged() {
            @Override
            public void ListPosChanged() {
                scrollBar.ScrollPositionChanged();
            }
        });

        this.childs.add(lv);
        this.childs.add(scrollBar);
    }

}