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    }