1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.jeuclid.elements.presentation.table;
20
21 import java.awt.Color;
22 import java.awt.Graphics2D;
23 import java.awt.geom.Dimension2D;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Locale;
27
28 import net.sourceforge.jeuclid.Constants;
29 import net.sourceforge.jeuclid.LayoutContext;
30 import net.sourceforge.jeuclid.context.InlineLayoutContext;
31 import net.sourceforge.jeuclid.context.Parameter;
32 import net.sourceforge.jeuclid.elements.JEuclidElement;
33 import net.sourceforge.jeuclid.elements.support.Dimension2DImpl;
34 import net.sourceforge.jeuclid.elements.support.ElementListSupport;
35 import net.sourceforge.jeuclid.elements.support.GraphicsSupport;
36 import net.sourceforge.jeuclid.elements.support.attributes.AttributesHelper;
37 import net.sourceforge.jeuclid.elements.support.attributes.HAlign;
38 import net.sourceforge.jeuclid.layout.GraphicsObject;
39 import net.sourceforge.jeuclid.layout.LayoutInfo;
40 import net.sourceforge.jeuclid.layout.LayoutStage;
41 import net.sourceforge.jeuclid.layout.LayoutView;
42 import net.sourceforge.jeuclid.layout.LayoutableNode;
43 import net.sourceforge.jeuclid.layout.LineObject;
44
45 import org.apache.batik.dom.AbstractDocument;
46 import org.apache.commons.logging.Log;
47 import org.apache.commons.logging.LogFactory;
48 import org.w3c.dom.Node;
49 import org.w3c.dom.mathml.MathMLLabeledRowElement;
50 import org.w3c.dom.mathml.MathMLNodeList;
51 import org.w3c.dom.mathml.MathMLTableCellElement;
52 import org.w3c.dom.mathml.MathMLTableElement;
53 import org.w3c.dom.mathml.MathMLTableRowElement;
54
55
56
57
58
59
60
61
62
63 public final class Mtable extends AbstractTableElement implements
64 MathMLTableElement {
65
66
67
68
69
70 public static final String ELEMENT = "mtable";
71
72
73 static final String ATTR_COLUMNALIGN = "columnalign";
74
75
76 static final String ATTR_ROWALIGN = "rowalign";
77
78
79 static final String ATTR_GROUPALIGN = "groupalign";
80
81
82 private static final String ATTR_ROWLINES = "rowlines";
83
84
85 private static final String ATTR_COLUMNLINES = "columnlines";
86
87
88 private static final String ATTR_ALIGN = "align";
89
90
91 private static final String ATTR_ALIGNMENTSCOPE = "alignmentscope";
92
93
94 private static final String ATTR_COLUMNWIDTH = "columnwidth";
95
96
97 private static final String ATTR_WIDTH = "width";
98
99
100 private static final String ATTR_ROWSPACING = "rowspacing";
101
102
103 private static final String ATTR_COLUMNSPACING = "columnspacing";
104
105
106 private static final String ATTR_FRAME = "frame";
107
108
109 private static final String ATTR_FRAMESPACING = "framespacing";
110
111
112 private static final String ATTR_EQUALROWS = "equalrows";
113
114
115 private static final String ATTR_EQUALCOLUMNS = "equalcolumns";
116
117
118 private static final String ATTR_DISPLAYSTYLE = "displaystyle";
119
120
121 private static final String ATTR_SIDE = "side";
122
123
124 private static final String ATTR_MINLABELSPACING = "minlabelspacing";
125
126
127 private static final String VALUE_NONE = "none";
128
129
130 private static final String VALUE_DASHED = "dashed";
131
132
133 private static final String VALUE_SOLID = "solid";
134
135 private static final long serialVersionUID = 1L;
136
137
138
139
140 private static final String DEFAULT_COLUMNSPACING = "0.8em";
141
142
143
144
145 private static final String DEFAULT_ROWSPACING = "1.0ex";
146
147
148
149
150 private static final String DEFAULT_FRAMESPACING = "0.4em 0.5ex";
151
152 private static final String VALUE_AUTO = "auto";
153
154
155
156
157 private static final Log LOGGER = LogFactory.getLog(Mtable.class);
158
159
160
161
162 public enum LineType {
163
164 NONE,
165
166 SOLID,
167
168 DASHED;
169
170
171
172
173
174
175
176
177 public static LineType parseLineType(final String s) {
178 final LineType retVal;
179 if (s.equalsIgnoreCase(Mtable.VALUE_SOLID)) {
180 retVal = SOLID;
181 } else if (s.equalsIgnoreCase(Mtable.VALUE_DASHED)) {
182 retVal = DASHED;
183 } else {
184 retVal = NONE;
185 }
186 return retVal;
187 }
188 };
189
190
191
192
193 private static final class VAlign {
194
195
196 static final int TOP = 0;
197
198
199 static final int BOTTOM = 1;
200
201
202 static final int CENTER = 2;
203
204
205 static final int BASELINE = 3;
206
207
208 static final int AXIS = 4;
209
210 static final String VALUE_TOP = "top";
211
212 static final String VALUE_BOTTOM = "bottom";
213
214 static final String VALUE_CENTER = "center";
215
216 static final String VALUE_BASELINE = "baseline";
217
218 static final String VALUE_AXIS = "axis";
219
220 static final VAlign BASELINE_ALIGN = new VAlign(Mtable.VAlign.BASELINE,
221 0);
222
223 private static final String INVALID_VERTICAL_ALIGNMENT_VALUE = "Invalid vertical alignment value: ";
224
225 private final int valign;
226
227 private final int alignTo;
228
229 private VAlign(final int align, final int relativeTo) {
230 this.valign = align;
231 this.alignTo = relativeTo;
232 }
233
234
235
236
237
238
239
240
241 public static VAlign parseString(final String s) {
242 if ((s == null) || (s.length() == 0)) {
243 return null;
244 }
245 final int align;
246 int relativeTo = 0;
247 final String s2 = s.trim().toLowerCase(Locale.ENGLISH);
248 final String s3;
249 if (s2.startsWith(Mtable.VAlign.VALUE_TOP)) {
250 align = Mtable.VAlign.TOP;
251 s3 = s2.substring(Mtable.VAlign.VALUE_TOP.length()).trim();
252 } else if (s2.startsWith(Mtable.VAlign.VALUE_BOTTOM)) {
253 align = Mtable.VAlign.BOTTOM;
254 s3 = s2.substring(Mtable.VAlign.VALUE_BOTTOM.length()).trim();
255 } else if (s2.startsWith(Mtable.VAlign.VALUE_CENTER)) {
256 align = Mtable.VAlign.CENTER;
257 s3 = s2.substring(Mtable.VAlign.VALUE_CENTER.length()).trim();
258 } else if (s2.startsWith(Mtable.VAlign.VALUE_BASELINE)) {
259 align = Mtable.VAlign.BASELINE;
260 s3 = s2.substring(Mtable.VAlign.VALUE_BASELINE.length()).trim();
261 } else if (s2.startsWith(Mtable.VAlign.VALUE_AXIS)) {
262 align = Mtable.VAlign.AXIS;
263 s3 = s2.substring(Mtable.VAlign.VALUE_AXIS.length()).trim();
264 } else {
265 Mtable.LOGGER
266 .warn(Mtable.VAlign.INVALID_VERTICAL_ALIGNMENT_VALUE
267 + s);
268 align = Mtable.VAlign.BASELINE;
269 s3 = "0";
270 }
271 if (s3.length() > 0) {
272 try {
273 relativeTo = Integer.parseInt(s3);
274 } catch (final NumberFormatException nfe) {
275 Mtable.LOGGER
276 .warn(Mtable.VAlign.INVALID_VERTICAL_ALIGNMENT_VALUE
277 + s);
278 }
279 }
280 return new VAlign(align, relativeTo);
281 }
282
283 public int getAlign() {
284 return this.valign;
285 }
286
287 public int getRelative() {
288 return this.alignTo;
289 }
290 }
291
292
293
294
295
296
297
298
299
300 public Mtable(final String qname, final AbstractDocument odoc) {
301 super(qname, odoc);
302
303 this.setDefaultMathAttribute(Mtable.ATTR_ALIGN,
304 Mtable.VAlign.VALUE_AXIS);
305 this.setDefaultMathAttribute(Mtable.ATTR_ROWALIGN,
306 Mtable.VAlign.VALUE_BASELINE);
307 this.setDefaultMathAttribute(Mtable.ATTR_COLUMNALIGN,
308 HAlign.ALIGN_CENTER);
309 this.setDefaultMathAttribute(Mtable.ATTR_GROUPALIGN, "{left}");
310 this
311 .setDefaultMathAttribute(Mtable.ATTR_ALIGNMENTSCOPE,
312 Constants.TRUE);
313 this
314 .setDefaultMathAttribute(Mtable.ATTR_COLUMNWIDTH,
315 Mtable.VALUE_AUTO);
316 this.setDefaultMathAttribute(Mtable.ATTR_WIDTH, Mtable.VALUE_AUTO);
317 this.setDefaultMathAttribute(Mtable.ATTR_ROWSPACING,
318 Mtable.DEFAULT_ROWSPACING);
319 this.setDefaultMathAttribute(Mtable.ATTR_COLUMNSPACING,
320 Mtable.DEFAULT_COLUMNSPACING);
321 this.setDefaultMathAttribute(Mtable.ATTR_ROWLINES, Mtable.VALUE_NONE);
322 this
323 .setDefaultMathAttribute(Mtable.ATTR_COLUMNLINES,
324 Mtable.VALUE_NONE);
325 this.setDefaultMathAttribute(Mtable.ATTR_FRAME, Mtable.VALUE_NONE);
326 this.setDefaultMathAttribute(Mtable.ATTR_FRAMESPACING,
327 Mtable.DEFAULT_FRAMESPACING);
328 this.setDefaultMathAttribute(Mtable.ATTR_EQUALROWS, Constants.FALSE);
329 this.setDefaultMathAttribute(Mtable.ATTR_EQUALCOLUMNS, Constants.FALSE);
330 this.setDefaultMathAttribute(Mtable.ATTR_DISPLAYSTYLE, Constants.FALSE);
331 this.setDefaultMathAttribute(Mtable.ATTR_SIDE, HAlign.ALIGN_RIGHT);
332 this.setDefaultMathAttribute(Mtable.ATTR_MINLABELSPACING,
333 Mtable.DEFAULT_COLUMNSPACING);
334 }
335
336
337 @Override
338 protected Node newNode() {
339 return new Mtable(this.nodeName, this.ownerDocument);
340 }
341
342
343 @Override
344 public LayoutContext getChildLayoutContext(final int childNum,
345 final LayoutContext context) {
346 return new InlineLayoutContext(this
347 .applyLocalAttributesToContext(context));
348 }
349
350 private float getFramespacingh(final LayoutContext now) {
351 if (Mtable.LineType.NONE.equals(this.getFrameAsLineType())) {
352 return 0;
353 }
354 final String spacing = this.getSpaceArrayEntry(this.getFramespacing(),
355 0);
356 return AttributesHelper.convertSizeToPt(spacing, now,
357 AttributesHelper.PT);
358 }
359
360 private float getFramespacingv(final LayoutContext now) {
361 if (Mtable.LineType.NONE.equals(this.getFrameAsLineType())) {
362 return 0;
363 }
364 final String spacing = this.getSpaceArrayEntry(this.getFramespacing(),
365 1);
366 return AttributesHelper.convertSizeToPt(spacing, now,
367 AttributesHelper.PT);
368 }
369
370
371 public String getRowlines() {
372 return this.getMathAttribute(Mtable.ATTR_ROWLINES);
373 }
374
375
376 public void setRowlines(final String rowlines) {
377 this.setAttribute(Mtable.ATTR_ROWLINES, rowlines);
378 }
379
380
381 public String getColumnlines() {
382 return this.getMathAttribute(Mtable.ATTR_COLUMNLINES);
383 }
384
385
386 public void setColumnlines(final String columnlines) {
387 this.setAttribute(Mtable.ATTR_COLUMNLINES, columnlines);
388 }
389
390 private LineType getRowLine(final int row) {
391 return Mtable.LineType.parseLineType(this.getSpaceArrayEntry(this
392 .getRowlines(), row));
393 }
394
395 private LineType getColumnLine(final int col) {
396 return Mtable.LineType.parseLineType(this.getSpaceArrayEntry(this
397 .getColumnlines(), col));
398 }
399
400 private LineType getFrameAsLineType() {
401 return Mtable.LineType.parseLineType(this.getFrame());
402 }
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 private String getSpaceArrayEntry(final String string, final int index) {
418 final String[] array;
419 if (string == null) {
420 array = new String[0];
421 } else {
422 array = string.split("\\s");
423 }
424 int cur = -1;
425 String last = "";
426 for (final String s : array) {
427 if (s.length() > 0) {
428 cur++;
429 if (cur == index) {
430 return s;
431 }
432 last = s;
433 }
434 }
435 return last;
436 }
437
438
439 public String getColumnwidth() {
440 return this.getMathAttribute(Mtable.ATTR_COLUMNWIDTH);
441 }
442
443
444 public void setColumnwidth(final String columnwidth) {
445 this.setAttribute(Mtable.ATTR_COLUMNWIDTH, columnwidth);
446 }
447
448
449 public String getWidth() {
450 return this.getMathAttribute(Mtable.ATTR_WIDTH);
451 }
452
453
454 public void setWidth(final String width) {
455 this.setAttribute(Mtable.ATTR_WIDTH, width);
456 }
457
458
459 public String getAlign() {
460 return this.getMathAttribute(Mtable.ATTR_ALIGN);
461 }
462
463
464 public void setAlign(final String align) {
465 this.setAttribute(Mtable.ATTR_ALIGN, align);
466 }
467
468
469 public String getAlignmentscope() {
470 return this.getMathAttribute(Mtable.ATTR_ALIGNMENTSCOPE);
471 }
472
473
474 public void setAlignmentscope(final String alignmentscope) {
475 this.setAttribute(Mtable.ATTR_ALIGNMENTSCOPE, alignmentscope);
476 }
477
478
479 public String getRowspacing() {
480 return this.getMathAttribute(Mtable.ATTR_ROWSPACING);
481 }
482
483
484 public void setRowspacing(final String rowspacing) {
485 this.setAttribute(Mtable.ATTR_ROWSPACING, rowspacing);
486 }
487
488
489 public String getColumnspacing() {
490 return this.getMathAttribute(Mtable.ATTR_COLUMNSPACING);
491 }
492
493
494 public void setColumnspacing(final String columnspacing) {
495 this.setAttribute(Mtable.ATTR_COLUMNSPACING, columnspacing);
496 }
497
498
499 public String getFrame() {
500 return this.getMathAttribute(Mtable.ATTR_FRAME);
501 }
502
503
504 public void setFrame(final String frame) {
505 this.setAttribute(Mtable.ATTR_FRAME, frame);
506 }
507
508
509 public String getFramespacing() {
510 return this.getMathAttribute(Mtable.ATTR_FRAMESPACING);
511 }
512
513
514 public void setFramespacing(final String framespacing) {
515 this.setAttribute(Mtable.ATTR_FRAMESPACING, framespacing);
516 }
517
518
519 public String getEqualrows() {
520 return this.getMathAttribute(Mtable.ATTR_EQUALROWS);
521 }
522
523
524 public void setEqualrows(final String equalrows) {
525 this.setAttribute(Mtable.ATTR_EQUALROWS, equalrows);
526 }
527
528
529 public String getEqualcolumns() {
530 return this.getMathAttribute(Mtable.ATTR_EQUALCOLUMNS);
531 }
532
533
534 public void setEqualcolumns(final String equalcolumns) {
535 this.setAttribute(Mtable.ATTR_EQUALCOLUMNS, equalcolumns);
536 }
537
538
539 public String getDisplaystyle() {
540 return this.getMathAttribute(Mtable.ATTR_DISPLAYSTYLE);
541 }
542
543
544 public void setDisplaystyle(final String displaystyle) {
545 this.setAttribute(Mtable.ATTR_DISPLAYSTYLE, displaystyle);
546 }
547
548
549 public String getSide() {
550 return this.getMathAttribute(Mtable.ATTR_SIDE);
551 }
552
553
554 public void setSide(final String side) {
555 this.setAttribute(Mtable.ATTR_SIDE, side);
556 }
557
558
559 public String getMinlabelspacing() {
560 return this.getMathAttribute(Mtable.ATTR_MINLABELSPACING);
561 }
562
563
564 public void setMinlabelspacing(final String minlabelspacing) {
565 this.setAttribute(Mtable.ATTR_MINLABELSPACING, minlabelspacing);
566 }
567
568
569 public MathMLNodeList getRows() {
570
571 return null;
572 }
573
574
575 public MathMLTableRowElement insertEmptyRow(final int index) {
576
577 return null;
578 }
579
580
581 public MathMLLabeledRowElement insertEmptyLabeledRow(final int index) {
582
583 return null;
584 }
585
586
587 public MathMLTableRowElement getRow(final int index) {
588
589 return null;
590 }
591
592
593 public MathMLTableRowElement insertRow(final int index,
594 final MathMLTableRowElement newRow) {
595
596 return null;
597 }
598
599
600 public MathMLTableRowElement setRow(final int index,
601 final MathMLTableRowElement newRow) {
602
603 return null;
604 }
605
606
607 public void deleteRow(final int index) {
608
609 }
610
611
612 public MathMLTableRowElement removeRow(final int index) {
613
614 return null;
615 }
616
617
618 public void deleteRow(final long index) {
619
620
621 }
622
623
624 public MathMLTableRowElement getRow(final long index) {
625
626 return null;
627 }
628
629
630 public MathMLLabeledRowElement insertEmptyLabeledRow(final long index) {
631
632 return null;
633 }
634
635
636 public MathMLTableRowElement insertEmptyRow(final long index) {
637
638 return null;
639 }
640
641
642 public MathMLTableRowElement insertRow(final long index,
643 final MathMLTableRowElement newRow) {
644
645 return null;
646 }
647
648
649 public MathMLTableRowElement removeRow(final long index) {
650
651 return null;
652 }
653
654
655 public MathMLTableRowElement setRow(final long index,
656 final MathMLTableRowElement newRow) {
657
658 return null;
659 }
660
661
662
663
664 @Override
665 public void layoutStageInvariant(final LayoutView view,
666 final LayoutInfo info, final LayoutStage stage,
667 final LayoutContext context) {
668
669 final Graphics2D g = view.getGraphics();
670 final LayoutContext now = this.applyLocalAttributesToContext(context);
671 final List<LayoutableNode> children = this.getChildrenToLayout();
672 final LayoutInfo[] rowInfos = new LayoutInfo[children.size()];
673 final LayoutableNode[] rowChild = new LayoutableNode[children.size()];
674 float y = 0;
675 int rows = 0;
676
677
678 final float vFrameSpacing = this.getFramespacingv(now);
679 float height = vFrameSpacing;
680 for (final LayoutableNode child : children) {
681 rowChild[rows] = child;
682 final LayoutInfo mtrInfo = view.getInfo(child);
683 y += mtrInfo.getAscentHeight(stage);
684 rowInfos[rows] = mtrInfo;
685 rows++;
686 mtrInfo.moveTo(0, y, stage);
687 y += mtrInfo.getDescentHeight(stage);
688 height = y;
689 y += AttributesHelper.convertSizeToPt(this.getSpaceArrayEntry(this
690 .getRowspacing(), rows), now, AttributesHelper.PT);
691 }
692 height += vFrameSpacing;
693
694 final float verticalShift = this.shiftTableVertically(stage, context,
695 g, rowInfos, rows, height);
696
697 final List<LayoutableNode>[] mtdChildren = this
698 .createListOfMtdChildren(rowChild, rows);
699 this.stretchAndAlignMtds(view, mtdChildren, rowInfos, rows, stage);
700
701 final List<Float> columnwidth = this.calculateBasicColumnWidth(view,
702 stage, rows, mtdChildren);
703
704
705
706 final float totalWidth = this.layoutColumnsHorizontally(view, stage,
707 now, rows, mtdChildren, columnwidth);
708
709 this.setRowWidth(stage, rowInfos, rows, totalWidth);
710
711 this.addRowLines(info, rowInfos, rows, totalWidth, stage, now);
712 this.addColumnLines(info, columnwidth, verticalShift, height, now);
713 this.addFrame(info, totalWidth, verticalShift, height, now);
714
715 final float hFrameSpacing = this.getFramespacingh(now);
716 final Dimension2D borderLeftTop = new Dimension2DImpl(hFrameSpacing,
717 vFrameSpacing);
718 final Dimension2D borderRightBottom = new Dimension2DImpl(
719 hFrameSpacing, vFrameSpacing);
720 ElementListSupport.fillInfoFromChildren(view, info, this, stage,
721 borderLeftTop, borderRightBottom);
722 }
723
724 private void addFrame(final LayoutInfo info, final float width,
725 final float verticalShift, final float height,
726 final LayoutContext now) {
727 final LineType lineType = this.getFrameAsLineType();
728 final boolean solid = Mtable.LineType.SOLID.equals(lineType);
729 final boolean dashed = Mtable.LineType.DASHED.equals(lineType);
730 if (dashed || solid) {
731 final float lineWidth = GraphicsSupport.lineWidth(now);
732 final float lineInset = lineWidth / 2.0f;
733 final Color color = (Color) now.getParameter(Parameter.MATHCOLOR);
734 final List<GraphicsObject> go = info.getGraphicObjects();
735 final float vFrameSpacing = this.getFramespacingv(now);
736
737 final float left = lineInset;
738 final float right = width - lineInset;
739 final float top = verticalShift + lineInset - vFrameSpacing;
740 final float bottom = height + verticalShift - lineInset;
741 go.add(new LineObject(left, top, right, top, lineWidth, color,
742 dashed));
743 go.add(new LineObject(left, bottom, right, bottom, lineWidth,
744 color, dashed));
745 go.add(new LineObject(left, top, left, bottom, lineWidth, color,
746 dashed));
747 go.add(new LineObject(right, top, right, bottom, lineWidth, color,
748 dashed));
749 }
750 }
751
752 private void addRowLines(final LayoutInfo info,
753 final LayoutInfo[] rowInfos, final int rows, final float width,
754 final LayoutStage stage, final LayoutContext now) {
755 final float lineWidth = GraphicsSupport.lineWidth(now);
756 final Color color = (Color) now.getParameter(Parameter.MATHCOLOR);
757
758 final float inFrameStart = this.getFramespacingh(now);
759 for (int row = 0; row < rows - 1; row++) {
760 final LineType lineType = this.getRowLine(row);
761 final boolean solid = Mtable.LineType.SOLID.equals(lineType);
762 final boolean dashed = Mtable.LineType.DASHED.equals(lineType);
763 if (dashed || solid) {
764 final float y = (rowInfos[row].getPosY(stage)
765 + rowInfos[row].getDescentHeight(stage)
766 + rowInfos[row + 1].getPosY(stage) - rowInfos[row + 1]
767 .getAscentHeight(stage)) / 2.0f;
768 info.getGraphicObjects().add(
769 new LineObject(inFrameStart, y, width - inFrameStart,
770 y, lineWidth, color, dashed));
771 }
772 }
773 }
774
775 private void addColumnLines(final LayoutInfo info,
776 final List<Float> columnwidth, final float verticalShift,
777 final float height, final LayoutContext now) {
778 final float lineWidth = GraphicsSupport.lineWidth(now);
779 final Color color = (Color) now.getParameter(Parameter.MATHCOLOR);
780 float x = this.getFramespacingh(now);
781
782 final float inFrameStart = this.getFramespacingv(now);
783 final float colsm1 = columnwidth.size() - 1;
784 for (int col = 0; col < colsm1; col++) {
785 final LineType lineType = this.getColumnLine(col);
786 final boolean solid = Mtable.LineType.SOLID.equals(lineType);
787 final boolean dashed = Mtable.LineType.DASHED.equals(lineType);
788 if (dashed || solid) {
789 final float halfSpace = this.getSpaceAfterColumn(now, col) / 2.0f;
790 x += columnwidth.get(col) + halfSpace;
791 info.getGraphicObjects().add(
792 new LineObject(x, verticalShift, x, height
793 + verticalShift - inFrameStart, lineWidth,
794 color, dashed));
795 x += halfSpace;
796 }
797 }
798 }
799
800 private void stretchAndAlignMtds(final LayoutView view,
801 final List<LayoutableNode>[] mtdChildren,
802 final LayoutInfo[] rowInfos, final int rows, final LayoutStage stage) {
803 for (int i = 0; i < rows; i++) {
804 final float rowAscent = rowInfos[i].getAscentHeight(stage);
805 final float rowDescent = rowInfos[i].getDescentHeight(stage);
806 for (final LayoutableNode n : mtdChildren[i]) {
807 final LayoutInfo mtdInfo = view.getInfo(n);
808
809 final VAlign valign = this.getVAlign((JEuclidElement) n, i);
810 final float verticalShift;
811 if (valign.getAlign() == Mtable.VAlign.TOP) {
812 verticalShift = -rowAscent + mtdInfo.getAscentHeight(stage);
813 } else if (valign.getAlign() == Mtable.VAlign.BOTTOM) {
814 verticalShift = rowDescent
815 - mtdInfo.getDescentHeight(stage);
816 } else if (valign.getAlign() == Mtable.VAlign.CENTER) {
817 verticalShift = (-rowAscent + rowDescent
818 + mtdInfo.getAscentHeight(stage) - mtdInfo
819 .getDescentHeight(stage)) / 2.0f;
820 } else if (valign.getAlign() == Mtable.VAlign.AXIS) {
821
822 verticalShift = (-rowAscent + rowDescent
823 + mtdInfo.getAscentHeight(stage) - mtdInfo
824 .getDescentHeight(stage)) / 2.0f;
825 } else {
826
827 verticalShift = 0.0f;
828 }
829 mtdInfo.shiftVertically(verticalShift, stage);
830 mtdInfo.setStretchAscent(rowAscent + verticalShift);
831 mtdInfo.setStretchDescent(rowDescent - verticalShift);
832 }
833 }
834 }
835
836 private float shiftTableVertically(final LayoutStage stage,
837 final LayoutContext context, final Graphics2D g,
838 final LayoutInfo[] rowInfos, final int rows, final float height) {
839
840
841
842
843
844
845 final float verticalShift = -this.getMiddleShift(g, context) - height
846 / 2.0f;
847
848 for (int i = 0; i < rows; i++) {
849 rowInfos[i].shiftVertically(verticalShift, stage);
850 }
851 return verticalShift;
852 }
853
854 @SuppressWarnings("unchecked")
855 private List<LayoutableNode>[] createListOfMtdChildren(
856 final LayoutableNode[] rowChild, final int rows) {
857 final List<LayoutableNode>[] mtdChildren = new List[rows];
858 for (int i = 0; i < rows; i++) {
859 if (rowChild[i] instanceof MathMLTableRowElement) {
860 mtdChildren[i] = rowChild[i].getChildrenToLayout();
861 } else {
862 mtdChildren[i] = new ArrayList<LayoutableNode>(1);
863 mtdChildren[i].add(rowChild[i]);
864 }
865 }
866 return mtdChildren;
867 }
868
869 private List<Float> calculateBasicColumnWidth(final LayoutView view,
870 final LayoutStage stage, final int rows,
871 final List<LayoutableNode>[] mtdChildren) {
872 final List<Float> columnwidth = new ArrayList<Float>();
873 for (int i = 0; i < rows; i++) {
874 int missing = mtdChildren[i].size() - columnwidth.size();
875 while (missing > 0) {
876 columnwidth.add(0.0f);
877 missing--;
878 }
879 int col = 0;
880 for (final LayoutableNode n : mtdChildren[i]) {
881 final float width = Math.max(columnwidth.get(col), view
882 .getInfo(n).getWidth(stage));
883 columnwidth.set(col, width);
884 col++;
885 }
886 }
887 if (Boolean.parseBoolean(this.getEqualcolumns())) {
888 this.makeEqual(columnwidth);
889 }
890 return columnwidth;
891 }
892
893 private void makeEqual(final List<Float> columnwidth) {
894 float maxWidth = 0.0f;
895 for (final Float width : columnwidth) {
896 maxWidth = Math.max(width, maxWidth);
897 }
898 final int cols = columnwidth.size();
899 for (int i = 0; i < cols; i++) {
900 columnwidth.set(i, maxWidth);
901 }
902 }
903
904 private void setRowWidth(final LayoutStage stage,
905 final LayoutInfo[] rowInfos, final int rows, final float totalWidth) {
906 for (int i = 0; i < rows; i++) {
907 rowInfos[i].setWidth(totalWidth, stage);
908 }
909 }
910
911 private float layoutColumnsHorizontally(final LayoutView view,
912 final LayoutStage stage, final LayoutContext now, final int rows,
913 final List<LayoutableNode>[] mtdChildren,
914 final List<Float> columnwidth) {
915 final float hFrameSpacing = this.getFramespacingh(now);
916 float totalWidth = hFrameSpacing;
917 for (int i = 0; i < rows; i++) {
918 float x = hFrameSpacing;
919 int col = 0;
920 for (final LayoutableNode n : mtdChildren[i]) {
921 final LayoutInfo mtdInfo = view.getInfo(n);
922 final HAlign halign = this.getHAlign((JEuclidElement) n, col);
923 final float colwi = columnwidth.get(col);
924 final float xo = halign.getHAlignOffset(stage, mtdInfo, colwi);
925 mtdInfo.moveTo(x + xo, mtdInfo.getPosY(stage), stage);
926
927 mtdInfo.setStretchWidth(colwi);
928 x += colwi;
929 totalWidth = Math.max(totalWidth, x);
930 x += this.getSpaceAfterColumn(now, col);
931 col++;
932 }
933 }
934 return totalWidth + hFrameSpacing;
935 }
936
937 private float getSpaceAfterColumn(final LayoutContext now, final int col) {
938 final float columnSpace = AttributesHelper.convertSizeToPt(this
939 .getSpaceArrayEntry(this.getColumnspacing(), col), now,
940 AttributesHelper.PT);
941 return columnSpace;
942 }
943
944 private HAlign getHAlign(final JEuclidElement n, final int col) {
945 assert n != null;
946 final HAlign retVal;
947 if (n instanceof MathMLTableCellElement) {
948 final MathMLTableCellElement cell = (MathMLTableCellElement) n;
949 final String alignString = cell.getColumnalign();
950 final HAlign halign = HAlign.parseString(alignString, null);
951 if (halign == null) {
952 retVal = this.getHAlign(n.getParent(), col);
953 } else {
954 retVal = halign;
955 }
956 } else if (n instanceof MathMLTableRowElement) {
957 final MathMLTableRowElement rowE = (MathMLTableRowElement) n;
958 final String alignArray = rowE.getColumnalign();
959 if ((alignArray != null) && (alignArray.length() > 0)) {
960 retVal = HAlign.parseString(this.getSpaceArrayEntry(alignArray,
961 col), HAlign.CENTER);
962 } else {
963 retVal = this.getHAlign(n.getParent(), col);
964 }
965 } else if (n instanceof MathMLTableElement) {
966 final MathMLTableElement table = (MathMLTableElement) n;
967 final String alignArray = table.getColumnalign();
968 if ((alignArray != null) && (alignArray.length() > 0)) {
969 retVal = HAlign.parseString(this.getSpaceArrayEntry(alignArray,
970 col), HAlign.CENTER);
971 } else {
972 retVal = HAlign.CENTER;
973 }
974 } else {
975 retVal = this.getHAlign(n.getParent(), col);
976 }
977 return retVal;
978 }
979
980 private VAlign getVAlign(final JEuclidElement n, final int row) {
981 assert n != null;
982 final VAlign retVal;
983 if (n instanceof MathMLTableCellElement) {
984 final MathMLTableCellElement cell = (MathMLTableCellElement) n;
985 final String alignString = cell.getRowalign();
986 final Mtable.VAlign valign = Mtable.VAlign.parseString(alignString);
987 if (valign == null) {
988 retVal = this.getVAlign(n.getParent(), row);
989 } else {
990 retVal = valign;
991 }
992 } else if (n instanceof MathMLTableRowElement) {
993 final MathMLTableRowElement rowE = (MathMLTableRowElement) n;
994 final String alignString = rowE.getRowalign();
995 final Mtable.VAlign valign = Mtable.VAlign.parseString(alignString);
996 if (valign == null) {
997 retVal = this.getVAlign(n.getParent(), row);
998 } else {
999 retVal = valign;
1000 }
1001 } else if (n instanceof MathMLTableElement) {
1002 final MathMLTableElement table = (MathMLTableElement) n;
1003 final String alignArray = table.getRowalign();
1004 if ((alignArray != null) && (alignArray.length() > 0)) {
1005 retVal = Mtable.VAlign.parseString(this.getSpaceArrayEntry(
1006 alignArray, row));
1007 } else {
1008 retVal = Mtable.VAlign.BASELINE_ALIGN;
1009 }
1010 } else {
1011 retVal = this.getVAlign(n.getParent(), row);
1012 }
1013 return retVal;
1014 }
1015
1016 }