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 }