001 package org.util.html.render; 002 003 004 import java.util.*; 005 import java.io.*; 006 import java.net.*; 007 import java.awt.*; 008 import java.awt.event.*; 009 import javax.swing.*; 010 import javax.swing.event.*; 011 012 import org.util.html.objects.*; 013 import org.util.html.event.*; 014 015 public class HTMLDocumentRenderer { 016 017 private HTMLDocument doc_; 018 private int offset_x_ = 0; 019 private int offset_y_ = 0; 020 private boolean finished_layout_; 021 private int screen_w_ = 1; 022 private int screen_h_ = 1; 023 private int width_; 024 private int height_; 025 private JPanel panel_; 026 private JScrollPane sp_; 027 028 private ArrayList<HTMLDocumentRendererListener> listener_list_ = new ArrayList<HTMLDocumentRendererListener>(); 029 030 public HTMLDocumentRenderer(HTMLDocument doc) { 031 doc_ = doc; 032 doc_.addHTMLListener(new HTMLRenderListener()); 033 panel_ = new JPanel(new HTMLLayoutManager()); 034 } 035 036 private volatile boolean do_layout_running_; 037 private volatile boolean do_layout_cancel_; 038 039 public void setScrollPane(JScrollPane sp) { 040 sp_ = sp; 041 } 042 043 public boolean doLayout(int w, int h) { 044 045 if(do_layout_running_) { 046 do_layout_cancel_ = true; 047 return false; 048 } 049 do_layout_running_ = true; 050 do_layout_cancel_ = false; 051 052 053 HTMLObject[] list = doc_.getObjectList(); 054 int now_x = 0; 055 int now_y = 0; 056 int line_height = 0; 057 HTMLObject last = null; 058 for(HTMLObject obj : list) { 059 060 if(!obj.isLayouted()) { 061 if(last != null) { 062 now_x = last.getNextX(); 063 now_y = last.getNextY(); 064 } 065 066 JComponent c = obj.getPanel(); 067 Dimension cd = c.getPreferredSize(); 068 int cw = (int)cd.getWidth(); 069 int ch = (int)cd.getHeight(); 070 071 if(now_x + cw > w) { 072 now_x = 0; 073 now_y += line_height; 074 line_height = ch; 075 } else { 076 line_height = Math.max(ch, line_height); 077 } 078 c.setLocation(now_x, now_y); 079 c.setSize(cw, ch); 080 c.setVisible(true); 081 obj.setLayouted(true); 082 083 now_x += cw; 084 obj.setNextXY(now_x, now_y); 085 } 086 last = obj; 087 } 088 width_ = w; 089 if(list.length>0) { 090 JComponent lc = list[list.length-1].getPanel(); 091 height_ = lc.getY()+lc.getHeight(); 092 } else { 093 height_ = 0; 094 } 095 finished_layout_ = true; 096 screen_w_ = w; 097 screen_h_ = h; 098 099 do_layout_running_ = false; 100 if(do_layout_cancel_) { 101 doLayout(w, h); 102 } 103 return true; 104 } 105 106 public int getOffsetX() { 107 return offset_x_; 108 } 109 public int getOffsetY() { 110 return offset_y_; 111 } 112 public int getWidth() { 113 return width_; 114 } 115 public int getHeight() { 116 return height_; 117 } 118 119 120 public void resized(int w, int h) { 121 HTMLObject[] list = doc_.getObjectList(); 122 if(list.length>1) 123 for(int i=0; i<list.length; i++) 124 list[i].setLayouted(false); 125 doLayout(w, h); 126 requestRepaint(); 127 } 128 129 public void addHTMLDocumentRendererListener(HTMLDocumentRendererListener listener){ 130 listener_list_.add(listener); 131 } 132 public void removeHTMLDocumentRendererListener(HTMLDocumentRendererListener listener){ 133 listener_list_.remove(listener); 134 } 135 136 public JComponent getPanel() { 137 return panel_; 138 } 139 140 private class HTMLRenderListener implements HTMLListener { 141 public void cleared(HTMLDocument doc) { 142 finished_layout_ = false; 143 requestRepaint(); 144 panel_.removeAll(); 145 panel_.revalidate(); 146 } 147 public void changed(HTMLDocument doc, HTMLObject obj) { 148 finished_layout_ = false; 149 for(HTMLObject o : doc_.getObjectList()) { 150 o.setLayouted(false); 151 } 152 panel_.revalidate(); 153 requestRepaint(); 154 } 155 public void added(HTMLDocument doc, HTMLObject obj) { 156 finished_layout_ = false; 157 panel_.add(obj.getPanel()); 158 panel_.revalidate(); 159 requestRepaint(); 160 } 161 public void removed(HTMLDocument doc, HTMLObject obj) { 162 } 163 } 164 private void requestRepaint() { 165 for(HTMLDocumentRendererListener listener : listener_list_) 166 listener.repaint(); 167 } 168 169 170 171 private class HTMLLayoutManager implements LayoutManager { 172 public void addLayoutComponent(String name, Component comp) { 173 174 } 175 public void layoutContainer(Container parent) { 176 int w = parent.getWidth(); 177 int h = parent.getHeight(); 178 doLayout(w, h); 179 } 180 public Dimension minimumLayoutSize(Container parent) { 181 return new Dimension(100, 100); 182 } 183 public Dimension preferredLayoutSize(Container parent) { 184 Dimension screen_size = sp_.getSize(); 185 int w = sp_.getWidth()-sp_.getVerticalScrollBar().getWidth()-3; 186 doLayout(w, 1); 187 return new Dimension(w, height_); 188 } 189 public void removeLayoutComponent(Component comp) { 190 191 } 192 } 193 }