1 /* |
1 /* |
2 * LazyScroller.scala |
2 * LazyScroller.scala |
3 * |
3 * |
4 * |
4 * TODO: clearer seperation of tasks: layout message_view, layout panel (with preferredsize), repaint, relayout, ... |
|
5 * + relayout on ValueIsAdjusting while scrolling |
|
6 * + scrolling *one* panel |
5 */ |
7 */ |
6 |
8 |
7 package isabelle.jedit |
9 package isabelle.jedit |
8 |
10 |
9 import java.io.{ ByteArrayInputStream, FileInputStream, InputStream } |
11 import java.io.{ ByteArrayInputStream, FileInputStream, InputStream } |
86 |
88 |
87 panel.setDocument(message, LazyScroller.baseURL) |
89 panel.setDocument(message, LazyScroller.baseURL) |
88 panel |
90 panel |
89 } |
91 } |
90 |
92 |
91 //calculates preferred size of panel and add it to the cache and view |
93 //calculates preferred size of panel |
92 def add_to_cache (message_no: Int, panel: XHTMLPanel) = { |
94 def calculate_preferred_size(panel: XHTMLPanel){ |
93 message_cache = message_cache.update (message_no, panel) |
|
94 //necessary for calculating preferred size of panel |
|
95 message_view.add (panel) |
95 message_view.add (panel) |
96 panel.setBounds (0, 0, message_view.getWidth, 1) // document has to fit into width |
96 panel.setBounds (0, 0, message_view.getWidth, 1) // document has to fit into width |
97 panel.doLayout (panel.getGraphics) //lay out, preferred size is set then |
97 panel.doLayout (panel.getGraphics) //lay out, preferred size is set then |
|
98 } |
|
99 |
|
100 //add panel to the cache |
|
101 def add_to_cache (message_no: Int, panel: XHTMLPanel) = { |
|
102 message_cache = message_cache.update (message_no, panel) |
|
103 calculate_preferred_size(panel) |
98 System.err.println("Added " + message_no + " with preferred Size " + panel.getPreferredSize + " to cache") |
104 System.err.println("Added " + message_no + " with preferred Size " + panel.getPreferredSize + " to cache") |
99 } |
105 } |
100 |
106 |
101 //render and load a message into cache, place its bottom at y-coordinate; |
107 //render and load a message into cache, place its bottom at y-coordinate; |
102 def set_message (message_no: Int, y: Int) = { |
108 def set_message (message_no: Int, y: Int) = { |
119 while (y >= 0 && n >= 0){ |
125 while (y >= 0 && n >= 0){ |
120 val panel = set_message (n, y) |
126 val panel = set_message (n, y) |
121 y = y - panel.getHeight |
127 y = y - panel.getHeight |
122 n = n - 1 |
128 n = n - 1 |
123 } |
129 } |
124 //clean cache (except for some elements on top and bottom, if existent) |
|
125 //TODO: find appropriate values |
|
126 //larger cache makes e.g. resizing slower |
|
127 if(message_cache.size > 20){ |
|
128 val min = n - 5 |
|
129 val max = message_no + 5 |
|
130 message_cache = message_cache filter (t => t match{case (no, _) => no >= min && no <= max}) |
|
131 } |
|
132 repaint() |
130 repaint() |
133 } |
131 } |
134 |
132 |
135 def add_message (message: Document) = { |
133 def add_message (message: Document) = { |
136 message_buffer += message |
134 message_buffer += message |
141 //event-handling has to be so general (without UNIT_INCR,...) |
139 //event-handling has to be so general (without UNIT_INCR,...) |
142 // because all events could be sent as TRACK e.g. on my mac |
140 // because all events could be sent as TRACK e.g. on my mac |
143 message_no = e.getValue |
141 message_no = e.getValue |
144 update_view |
142 update_view |
145 } |
143 } |
146 |
144 |
|
145 // handle Component-Events |
|
146 override def componentShown(e: ComponentEvent){} |
147 override def componentHidden(e: ComponentEvent){} |
147 override def componentHidden(e: ComponentEvent){} |
148 override def componentMoved(e: ComponentEvent){} |
148 override def componentMoved(e: ComponentEvent){} |
149 override def componentResized(e: ComponentEvent){ |
149 override def componentResized(e: ComponentEvent){ |
150 // update_cache: insert panels into new cache -> preferred size is calculated |
150 // remove all hidden messages from cache |
151 val panels = message_cache.elements |
151 // TODO: move to unlayouted cache |
152 message_cache = message_cache.empty |
152 message_cache = message_cache filter ( pair => pair match {case (no, _) => |
153 panels foreach (pair => pair match{case (no, pa) => add_to_cache (no, pa)}) |
153 no <= message_no && no >= message_no - message_view.getComponents.length}) |
154 vscroll.setMaximum (Math.max(1, message_buffer.length)) |
154 //calculate preferred size for each panel |
|
155 message_cache foreach (pair => pair match { case (_, pa) => |
|
156 calculate_preferred_size (pa) |
|
157 }) |
155 update_view |
158 update_view |
156 } |
159 } |
157 override def componentShown(e: ComponentEvent){} |
|
158 |
160 |
159 //register somewhere |
161 //register somewhere |
|
162 // TODO: only testing atm |
160 Plugin.plugin.stateUpdate.add(state => { |
163 Plugin.plugin.stateUpdate.add(state => { |
161 var i = 0 |
164 var i = 0 |
162 if(state != null) while (i < 500) { |
165 if(state != null) while (i < 500) { |
163 add_message(state.document) |
166 add_message(state.document) |
164 i += 1 |
167 i += 1 |