/* * Freeplane - mind map editor * Copyright (C) 2012 Freeplane team and others * * this file is created by Dimitry Polivaev in 2012. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.freeplane.core.ui.components.html; import java.io.*; import java.awt.*; import java.net.URL; import javax.swing.*; import javax.swing.plaf.basic.BasicHTML; import javax.swing.text.*; import javax.swing.text.html.*; public class ScaledHTML extends BasicHTML{ /** * Create an html renderer for the given component and * string of html. */ public static View createHTMLView(JComponent c, String html) { ScaledEditorKit kit = ScaledEditorKit.create(); Document doc = kit.createDefaultDocument(c.getFont(), c.getForeground()); Object base = c.getClientProperty(documentBaseKey); if (base instanceof URL) { ((HTMLDocument)doc).setBase((URL)base); } Reader r = new StringReader(html); try { kit.read(r, doc, 0); } catch (Throwable e) { } ViewFactory f = kit.getViewFactory(); View hview = f.create(doc.getDefaultRootElement()); View v = new Renderer(c, f, hview); return v; } public static void updateRenderer(JComponent c, String text) { View value = null; try{ View oldValue = (View)c.getClientProperty(propertyKey); if (isHTMLString(text)) { value = ScaledHTML.createHTMLView(c, text); } if (value != oldValue && oldValue != null) { for (int i = 0; i < oldValue.getViewCount(); i++) { oldValue.getView(i).setParent(null); } } } finally{ c.putClientProperty(BasicHTML.propertyKey, value); } } /** * Overrides to the default stylesheet. Should consider * just creating a completely fresh stylesheet. */ static final String styleChanges = "p { margin-top: 0; margin-bottom: 0; margin-left: 0; margin-right: 0 }" + "body { margin-top: 0; margin-bottom: 0; margin-left: 0; margin-right: 0 }"; /** * Root text view that acts as an HTML renderer. */ public static class Renderer extends View { Renderer(JComponent c, ViewFactory f, View v) { super(null); setSizeRunning = true; host = c; factory = f; view = v; view.setParent(this); // initially layout to the preferred size setSize(view.getPreferredSpan(X_AXIS), view.getPreferredSpan(Y_AXIS)); } public AttributeSet getAttributes() { return null; } public float getPreferredSpan(int axis) { if (axis == X_AXIS) { // width currently laid out to return width; } return view.getPreferredSpan(axis); } public float getMinimumSpan(int axis) { return view.getMinimumSpan(axis); } public float getMaximumSpan(int axis) { return Integer.MAX_VALUE; } public void preferenceChanged(View child, boolean width, boolean height) { if(! setSizeRunning) setSize(view.getPreferredSpan(X_AXIS), view.getPreferredSpan(Y_AXIS)); host.revalidate(); host.repaint(); } public float getAlignment(int axis) { return view.getAlignment(axis); } public void paint(Graphics g, Shape allocation) { Rectangle alloc = allocation.getBounds(); view.setSize(alloc.width, alloc.height); view.paint(g, allocation); } public void setParent(View parent) { throw new Error("Can't set parent on root view"); } public int getViewCount() { return 1; } public View getView(int n) { return view; } public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException { return view.modelToView(pos, a, b); } public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a) throws BadLocationException { return view.modelToView(p0, b0, p1, b1, a); } public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) { return view.viewToModel(x, y, a, bias); } public Document getDocument() { return view.getDocument(); } public int getStartOffset() { return view.getStartOffset(); } public int getEndOffset() { return view.getEndOffset(); } public Element getElement() { return view.getElement(); } public void setSize(float width, float height) { setSizeRunning = true; this.width = (int) width; view.setSize(width, height); setSizeRunning = false; } public void resetSize() { setSize(0, 0); setSize(view.getPreferredSpan(X_AXIS), view.getPreferredSpan(Y_AXIS)); } public Container getContainer() { return host; } public ViewFactory getViewFactory() { return factory; } private int width; private View view; private ViewFactory factory; private JComponent host; private boolean setSizeRunning; } }