KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > joshy > html > InlineLayout


1 package org.joshy.html;
2
3 import java.util.List JavaDoc;
4 import java.awt.Point JavaDoc;
5 import java.awt.Rectangle JavaDoc;
6 import java.awt.font.LineMetrics JavaDoc;
7 import java.awt.Color JavaDoc;
8 import java.awt.Graphics JavaDoc;
9 import java.awt.Graphics2D JavaDoc;
10 import java.awt.Font JavaDoc;
11
12 import org.w3c.dom.Element JavaDoc;
13 import org.w3c.dom.Node JavaDoc;
14 import org.joshy.u;
15
16 import org.joshy.html.box.InlineBox;
17 import org.joshy.html.box.LineBox;
18 import org.joshy.html.box.*;
19 import org.joshy.html.Context;
20 import org.joshy.html.util.GraphicsUtil;
21 import org.joshy.html.util.TextUtil;
22 import org.joshy.html.util.FontUtil;
23 import org.joshy.html.util.InlineUtil;
24 import org.joshy.html.util.LineBreaker;
25 import org.joshy.html.painter.*;
26
27 public class InlineLayout extends BoxLayout {
28
29
30 public Box layoutChildren(Context c, Box box) {
31     //u.p("InlineLayout.layoutChildren(: " + box);
32
//u.p("parent box = " + c.parent_box);
33
//u.p("placement point = " + c.placement_point);
34
if(!box.isAnonymous()) {
35         if(isBlockLayout(box.getElement(),c)) {
36             return super.layoutChildren(c,box);
37         }
38     }
39
40     int debug_counter = 0;
41     int childcount = 0;
42     BlockBox block = (BlockBox)box;
43
44     // calculate the initial position and dimensions
45
Rectangle JavaDoc bounds = new Rectangle JavaDoc();
46     bounds.width = c.getExtents().width;
47     bounds.width -= box.margin.left + box.border.left + box.padding.left +
48         box.padding.right + box.border.right + box.margin.right;
49     bounds.x = 0;
50     bounds.y = 0;
51     bounds.height = 0;
52     int remaining_width = bounds.width;
53
54     // account for text-indent
55
LineBox curr_line = new LineBox();
56     curr_line.x = bounds.x;
57     //curr_line.width = remaining_width;
58
curr_line.width = 0;
59     Element JavaDoc elem = block.getElement();
60     remaining_width = InlineUtil.doTextIndent(c,elem,remaining_width,curr_line);
61     LineBox prev_line = new LineBox();
62     prev_line.y = bounds.y;
63     prev_line.height = 0;
64     InlineBox prev_inline = null;
65     
66     //boolean adjusted_left_tab = false;
67
if(c.getLeftTab().y > 0) {
68         c.getLeftTab().y -= c.placement_point.y;
69     }
70     if(c.getRightTab().y > 0) {
71         c.getRightTab().y -= c.placement_point.y;
72     }
73     if(c.getRightTab().y < 0) {
74         c.getRightTab().y = 0;
75     }
76     if(c.getLeftTab().y < 0) {
77         c.getLeftTab().y = 0;
78     }
79
80     InlineBox prev_align_inline = null;
81     List JavaDoc inline_node_list = null;
82     if(box.isAnonymous()) {
83         inline_node_list = ((AnonymousBlockBox)box).node_list;
84     } else {
85         inline_node_list = InlineUtil.getInlineNodeList(elem,elem,c);
86     }
87
88     // loop until no more nodes
89
Node JavaDoc current_node = InlineUtil.nextTextNode(inline_node_list);
90     TextUtil.stripWhitespace(c,current_node,elem);
91
92     // ajdust the first line for tabs
93
remaining_width = adjustForTab(c, prev_line, remaining_width);
94
95     while(current_node != null) {
96         // loop until no more text in this node
97
while(true) {
98             // test if there is no more text in the current text node
99
// if there is a prev, and if the prev was part of this current node
100
if(prev_inline != null && prev_inline.node == current_node) {
101                 //u.p("prev inline = " + prev_inline);
102
//u.p("current text len = " + current_node.getNodeValue().length());
103
// replaced elements aren't split, so done with this one
104
if(isReplaced(current_node)) {
105                     //u.p("it's replaced. breaking");
106
break;
107                 }
108                 if(isFloatedBlock(current_node,c)) {
109                     break;
110                 }
111                 if(InlineUtil.isBreak(current_node)) {
112                     break;
113                 }
114                 // if no more unused text in this node
115
if(prev_inline.end_index >= current_node.getNodeValue().length()) {
116                     // then break
117
//u.p("used up all of the text. breaking");
118
break;
119                 }
120             }
121             if(bounds.width < 100) {
122                 //u.p("warning. width < 0 " + width);
123
}
124             debug_counter++;
125             if(debug_counter > 143) {
126                 u.on();
127                 u.p("previous inline = " + prev_inline);
128                 u.p("current line = " + curr_line);
129                 u.p("lines = ");
130                 //u.p(block.boxes);
131
u.p("current node = " + current_node + " text= " + current_node.getNodeValue());
132                 u.p("rem width = " + remaining_width + " width " + bounds.width);
133             }
134             if(debug_counter > 143) {
135                 u.p("element = " + elem);
136                 org.joshy.x.p(elem);
137                 u.p("previous inline = " + prev_inline);
138                 u.p("current inline = " + curr_line);
139                 u.p("lines = ");
140                 //u.p(block.boxes);
141
u.p("db 1 hit");
142                 System.exit(-1);
143             }
144             // look at current inline
145
// break off the longest section that will fit
146
//u.p("looking for another inline from the text: " + current_node.getNodeValue());
147
InlineBox new_inline = this.calculateInline(c,current_node,remaining_width,bounds.width,
148                 curr_line, prev_inline, elem, prev_align_inline);
149             //u.p("new inline box: " + new_inline);
150

151             // if this inline needs to be on a new line
152
if(new_inline.break_before && !new_inline.floated) {
153                 // finish up the current line
154
remaining_width = bounds.width;
155                 saveLine(curr_line, prev_line, elem, bounds.width, bounds.x, c, block);
156                 bounds.height += curr_line.height;
157                 prev_line = curr_line;
158                 curr_line = new LineBox();
159                 curr_line.x = bounds.x;
160                 // adjust remaining width for floats
161
//u.p("left tab = " + left_tab + " right tab = " + c.getRightTab());
162
//if(c.getLeftTab().y > 0) {
163
remaining_width = adjustForTab(c, prev_line, remaining_width);
164                 //curr_line.width = remaining_width;
165
curr_line.width = 0;
166             }
167
168             // save the new inline to the list
169
curr_line.addChild(new_inline);
170
171             // calc new height of the line
172
// don't count the inline towards the line height and
173
//line baseline if it's a floating inline.
174
if(!isFloated(new_inline,c)) {
175                 if(!this.isFloatedBlock(new_inline.node,c)) {
176                     if(new_inline.height + new_inline.y > curr_line.height) {
177                         curr_line.height = new_inline.height + new_inline.y;
178                     }
179                     if(new_inline.baseline > curr_line.baseline) {
180                         curr_line.baseline = new_inline.baseline;
181                     }
182                 }
183             }
184
185             InlineUtil.handleFloated(c, new_inline, curr_line, bounds.width, elem);
186
187             // calc new width of the line
188
curr_line.width += new_inline.width;
189             // reduce the available width
190
remaining_width = remaining_width - new_inline.width;
191             // if the last inline was at the end of a line, then go to next line
192
if(new_inline.break_after) {
193                 // then remaining_width = max_width
194
remaining_width = bounds.width;
195                 //u.p("width = " + width);
196
// save the line
197
//u.p("curr line = " + curr_line);
198
saveLine(curr_line, prev_line,elem,bounds.width,bounds.x,c,block);
199                 bounds.height += curr_line.height;
200                 //u.p("saved line: " + curr_line);
201
prev_line = curr_line;
202                 curr_line = new LineBox();
203                 curr_line.x = bounds.x;
204                 // adjust remaining width for floats
205
//u.p("rem width = " + remaining_width);
206
//if(c.getLeftTab().y > 0) {
207
remaining_width = adjustForTab(c, prev_line, remaining_width);
208                 //curr_line.width = remaining_width;
209
curr_line.width = 0;
210                 //u.p("now rem width = " + remaining_width);
211
}
212
213             // set the inline to use for left alignment
214
if(!isFloated(new_inline,c)) {
215                 prev_align_inline = new_inline;
216             } else {
217                 prev_align_inline = prev_inline;
218             }
219             prev_inline = new_inline;
220         }
221         current_node = InlineUtil.nextTextNode(inline_node_list);
222         TextUtil.stripWhitespace(c,current_node,elem);
223     }
224
225     saveLine(curr_line,prev_line,elem,bounds.width,bounds.x,c,block);
226     //u.p("saving line 2: " + curr_line);
227
bounds.height += curr_line.height;
228
229     block.width = bounds.width;
230     block.height = bounds.height;
231     block.x = 0;
232     block.y = 0;
233     //u.p("returning final block of: " + box);
234
//u.p("last tab = " + c.getLeftTab());
235
//if(adjusted_left_tab) {
236
c.getLeftTab().y += c.placement_point.y;
237     c.getRightTab().y += c.placement_point.y;
238     //}
239
//c.setLeftTab(old_left_tab);
240
//u.p("final tabl = " + c.getLeftTab());
241
return block;
242 }
243
244
245 private int adjustForTab(Context c, LineBox prev_line, int remaining_width) {
246     if(prev_line.y < c.getLeftTab().y) {
247         remaining_width -= c.getLeftTab().x;
248         //u.p("substracting off : " + c.getLeftTab().x);
249
}
250     if(prev_line.y + prev_line.height < c.getRightTab().y) {
251         remaining_width -= c.getRightTab().x;
252     //u.p("rem width = " + remaining_width);
253
}
254     return remaining_width;
255 }
256
257
258
259 // get longest inline possible
260
private InlineBox calculateInline(Context c, Node JavaDoc node, int avail, int max_width,
261      LineBox line, InlineBox prev, Element JavaDoc containing_block, InlineBox prev_align) {
262      //u.p("line calc with avail = " + avail);
263
// calculate the starting index
264
int start = 0;
265     if(prev != null && prev.node == node) {
266         start = prev.end_index;
267     }
268
269     // get the text of the node
270
String JavaDoc text = node.getNodeValue();
271     //u.p("calc inline for node: " + node);
272
//u.p("text = " + text);
273

274     // transform the text if required (like converting to caps)
275
// this must be done before any measuring since it might change the
276
// size of the text
277
text = TextUtil.transformText(c,node,text);
278     //u.p("text = " + text);
279

280     if(isReplaced(node)) {
281         return LineBreaker.generateReplacedInlineBox(c,node,avail,prev, text,prev_align);
282     }
283     if(isFloatedBlock(node,c)) {
284         return LineBreaker.generateFloatedBlockInlineBox(c,node,avail,prev, text,prev_align);
285     }
286     if(InlineUtil.isBreak(node)) {
287         return LineBreaker.generateBreakInlineBox(node);
288     }
289     if(LineBreaker.isWhitespace(c,containing_block)) {
290         return LineBreaker.generateWhitespaceInlineBox(c,node,start,prev,text,prev_align);
291     }
292     // ==== unbreakable long word =====
293
if(LineBreaker.isUnbreakableLine(c,node,start,text,avail)) {
294         return LineBreaker.generateUnbreakableInlineBox(c,node,start,text,prev,prev_align);
295     }
296     // rest of this string can fit on the line
297
if(LineBreaker.canFitOnLine(c,node,start,text,avail)) {
298         return LineBreaker.generateRestOfTextNodeInlineBox(c,node,start,text,prev,prev_align);
299     }
300     // normal multiline break
301
return LineBreaker.generateMultilineBreak(c,node,start,text,prev,prev_align,avail);
302 }
303
304
305
306
307 private void saveLine(LineBox line_to_save, LineBox prev_line, Element JavaDoc containing_block, int width, int x,
308     Context c, BlockBox block) {
309
310
311     //line_to_save.x = x;
312

313     // account for text-align
314
String JavaDoc text_align = c.css.getStringProperty(containing_block,"text-align");
315     //u.p("text-align = " + text_align);
316
if(text_align != null) {
317         if(text_align.equals("right")) {
318             //u.p("initial line: " + line_to_save);
319
//u.p("x = " + x + " width = " + width);
320
line_to_save.x = x + width - line_to_save.width;
321             //line_to_save.x = x + line_to_save.width - width;
322
//u.p("saved line: " + line_to_save);
323
}
324         if(text_align.equals("center")) {
325             line_to_save.x = x + (width - line_to_save.width)/2;
326         }
327     }
328
329     // set the y
330
line_to_save.y = prev_line.y + prev_line.height;
331
332     //if(c.getLeftTab().y >0) {
333
//u.p("line to save y = " + line_to_save.y);
334
//u.p("left tab y = " + c.getLeftTab().y);
335
if(line_to_save.y < c.getLeftTab().y) {
336         line_to_save.x+= c.getLeftTab().x;
337     //}
338
//if(c.getLeftTab().y > 0) {
339
//c.getLeftTab().y -= line_to_save.height;
340
}
341     //if(c.getLeftTab().y <= 0) {
342
//c.getLeftTab().x = 0;
343
//}
344

345     if(c.getRightTab().y >0) {
346         //line_to_save.x+= c.getRightTab().x;
347
//}
348
//if(c.getRightTab().y > 0) {
349
//c.getRightTab().y -= line_to_save.height;
350
}
351     //if(c.getRightTab().y <= 0) {
352
//c.getRightTab().x = 0;
353
//}
354

355     FontUtil.setupVerticalAlign(c,containing_block,line_to_save);
356     block.addChild(line_to_save);
357     //u.p("final saved line = " + line_to_save);
358
//u.p("block = " + block.hashCode());
359
}
360
361
362 public void paintComponent(Context c, Box box) {
363     //u.p("InlineLayout.paintComponent() " + box);
364
//u.dump_stack();
365
if(box.isAnonymous()) {
366         //u.p("InlineLayout.paintComponent() : " + box);
367
InlinePainter.paintInlineContext(c,box);
368         return;
369     }
370     if(this.isBlockLayout(box.getElement(),c)) {
371         //u.p("InlineLayout.paintComponent is block context: " + box);
372
super.paintComponent(c,box);
373         return;
374     }
375     //u.p("InlineLayout.paintComponent()" + box);
376
InlinePainter.paintInlineContext(c,box);
377 }
378
379
380 public void paintChildren(Context c, Box box) {
381     //u.p("InlineLayout.paintChildren() " + box);
382
if(box.isAnonymous()) {
383         //u.p("it's anonymous so no children");
384
return;
385     }
386     if(this.isBlockLayout(box.getElement(),c)) {
387         //u.p("is block. doing super");
388
super.paintChildren(c,box);
389     }
390 }
391
392 }
393
394
Popular Tags