Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.layout;
027
028import java.util.ArrayList;
029import java.util.Collections;
030import java.util.List;
031import javafx.beans.property.BooleanProperty;
032import javafx.beans.property.DoubleProperty;
033import javafx.beans.property.ObjectProperty;
034import javafx.css.CssMetaData;
035import javafx.css.StyleableBooleanProperty;
036import javafx.css.StyleableDoubleProperty;
037import javafx.css.StyleableObjectProperty;
038import javafx.css.StyleableProperty;
039import javafx.geometry.Insets;
040import javafx.geometry.Orientation;
041import javafx.geometry.Pos;
042import javafx.geometry.VPos;
043import javafx.scene.Node;
044import com.sun.javafx.css.converters.BooleanConverter;
045import com.sun.javafx.css.converters.EnumConverter;
046import com.sun.javafx.css.converters.SizeConverter;
047import javafx.css.Styleable;
048import javafx.geometry.HPos;
049
050
051
052/**
053 * HBox lays out its children in a single horizontal row.
054 * If the hbox has a border and/or padding set, then the contents will be layed
055 * out within those insets.
056 * <p>
057 * HBox example:
058 * <pre><code>
059 *     HBox hbox = new HBox(8); // spacing = 8
060 *     hbox.getChildren().addAll(new Label("Name:), new TextBox());
061 * </code></pre>
062 *
063 * HBox will resize children (if resizable) to their preferred widths and uses its
064 * fillHeight property to determine whether to resize their heights to
065 * fill its own height or keep their heights to their preferred (fillHeight defaults to true).
066 * The alignment of the content is controlled by the alignment property,
067 * which defaults to Pos.TOP_LEFT.
068 * <p>
069 * If an hbox is resized larger than its preferred width, by default it will keep
070 * children to their preferred widths, leaving the extra space unused.  If an
071 * application wishes to have one or more children be allocated that extra space
072 * it may optionally set an hgrow constraint on the child.  See "Optional Layout
073 * Constraints" for details.
074 * <p>
075 * HBox lays out each managed child regardless of the child's
076 * visible property value; unmanaged children are ignored.</p>
077 *
078 * <h4>Resizable Range</h4>
079 *
080 * An hbox's parent will resize the hbox within the hbox's resizable range
081 * during layout.   By default the hbox computes this range based on its content
082 * as outlined in the table below.
083 * <table border="1">
084 * <tr><td></td><th>width</th><th>height</th></tr>
085 * <tr><th>minimum</th>
086 * <td>left/right insets plus the sum of each child's min width plus spacing between each child.</td>
087 * <td>top/bottom insets plus the largest of the children's min heights.</td></tr>
088 * <tr><th>preferred</th>
089 * <td>left/right insets plus the sum of each child's pref width plus spacing between each child.</td>
090 * <td>top/bottom insets plus the largest of the children's pref heights.</td></tr>
091 * <tr><th>maximum</th>
092 * <td>Double.MAX_VALUE</td><td>Double.MAX_VALUE</td></tr>
093 * </table>
094 * <p>
095 * An hbox's unbounded maximum width and height are an indication to the parent that
096 * it may be resized beyond its preferred size to fill whatever space is assigned
097 * to it.
098 * <p>
099 * HBox provides properties for setting the size range directly.  These
100 * properties default to the sentinel value USE_COMPUTED_SIZE, however the
101 * application may set them to other values as needed:
102 * <pre><code>
103 *     <b>hbox.setPrefWidth(400);</b>
104 * </code></pre>
105 * Applications may restore the computed values by setting these properties back
106 * to USE_COMPUTED_SIZE.
107 * <p>
108 * HBox does not clip its content by default, so it is possible that childrens'
109 * bounds may extend outside its own bounds if a child's min size prevents it from
110 * being fit within the hbox.</p>
111 *
112 * <h4>Optional Layout Constraints</h4>
113 *
114 * An application may set constraints on individual children to customize HBox's layout.
115 * For each constraint, HBox provides a static method for setting it on the child.
116 * <p>
117 * <table border="1">
118 * <tr><th>Constraint</th><th>Type</th><th>Description</th></tr>
119 * <tr><td>hgrow</td><td>javafx.scene.layout.Priority</td><td>The horizontal grow priority for the child.</td></tr>
120 * <tr><td>margin</td><td>javafx.geometry.Insets</td><td>Margin space around the outside of the child.</td></tr>
121 * </table>
122 * <p>
123 * For example, if an hbox needs the TextField to be allocated all extra space:
124 * <pre><code>
125 *     HBox hbox = new HBox();
126 *     TextField field = new TextField();
127 *     <b>HBox.setHgrow(field, Priority.ALWAYS);</b>
128 *     hbox.getChildren().addAll(new Label("Search:"), field, new Button("Go"));
129 * </code></pre>
130 *
131 * If more than one child has the same grow priority set, then the hbox will
132 * allocate equal amounts of space to each.  HBox will only grow a child up to
133 * its maximum width, so if the child has a max width other than Double.MAX_VALUE,
134 * the application may need to override the max to allow it to grow.
135 * For example:
136 * <pre><code>
137 *     HBox hbox = new HBox();
138 *     Button button1 = new Button("Add");
139 *     Button button2 = new Button("Remove");
140 *     <b>HBox.setHgrow(button1, Priority.ALWAYS);
141 *     HBox.setHgrow(button2, Priority.ALWAYS);
142 *     button1.setMaxWidth(Double.MAX_VALUE);
143 *     button2.setMaxWidth(Double.MAX_VALUE);</b>
144 *     hbox.getChildren().addAll(button1, button2);
145 * </code></pre>
146 */
147public class HBox extends Pane {
148
149    private boolean biasDirty = true;
150    private boolean performingLayout = false;
151    private Orientation bias;
152
153    /********************************************************************
154     *  BEGIN static methods
155     ********************************************************************/
156    private static final String MARGIN_CONSTRAINT = "hbox-margin";
157    private static final String HGROW_CONSTRAINT = "hbox-hgrow";
158
159    /**
160     * Sets the horizontal grow priority for the child when contained by an hbox.
161     * If set, the hbox will use the priority to allocate additional space if the
162     * hbox is resized larger than it's preferred width.
163     * If multiple hbox children have the same horizontal grow priority, then the
164     * extra space will be split evening between them.
165     * If no horizontal grow priority is set on a child, the hbox will never
166     * allocate it additional horizontal space if available.
167     * Setting the value to null will remove the constraint.
168     * @param child the child of an hbox
169     * @param value the horizontal grow priority for the child
170     */
171    public static void setHgrow(Node child, Priority value) {
172        setConstraint(child, HGROW_CONSTRAINT, value);
173    }
174
175    /**
176     * Returns the child's hgrow constraint if set.
177     * @param child the child node of an hbox
178     * @return the horizontal grow priority for the child or null if no priority was set
179     */
180    public static Priority getHgrow(Node child) {
181        return (Priority)getConstraint(child, HGROW_CONSTRAINT);
182    }
183
184    /**
185     * Sets the margin for the child when contained by an hbox.
186     * If set, the hbox will layout the child with the margin space around it.
187     * Setting the value to null will remove the constraint.
188     * @param child the child mode of the hbox
189     * @param value the margin of space around the child
190     */
191    public static void setMargin(Node child, Insets value) {
192        setConstraint(child, MARGIN_CONSTRAINT, value);
193    }
194
195    /**
196     * Returns the child's margin constraint if set.
197     * @param child the child node of an hbox
198     * @return the margin for the child or null if no margin was set
199     */
200    public static Insets getMargin(Node child) {
201        return (Insets)getConstraint(child, MARGIN_CONSTRAINT);
202    }
203
204    /**
205     * Removes all hbox constraints from the child node.
206     * @param child the child node
207     */
208    public static void clearConstraints(Node child) {
209        setHgrow(child, null);
210        setMargin(child, null);
211    }
212
213    /********************************************************************
214     *  END static methods
215     ********************************************************************/
216
217    /**
218     * Creates an HBox layout with spacing = 0.
219     */
220    public HBox() {
221        super();
222    }
223
224    /**
225     * Creates an HBox layout with the specified spacing between children.
226     * @param spacing the amount of horizontal space between each child
227     */
228    public HBox(double spacing) {
229        this();
230        setSpacing(spacing);
231    }
232
233    /**
234     * Creates an HBox layout with spacing = 0.
235     * @param children The initial set of children for this pane.
236     */
237    public HBox(Node... children) {
238        super();
239        getChildren().addAll(children);
240    }
241
242    /**
243     * Creates an HBox layout with the specified spacing between children.
244     * @param spacing the amount of horizontal space between each child
245     * @param children The initial set of children for this pane.
246     */
247    public HBox(double spacing, Node... children) {
248        this();
249        setSpacing(spacing);
250        getChildren().addAll(children);
251    }
252
253    /**
254     * The amount of horizontal space between each child in the hbox.
255     */
256    public final DoubleProperty spacingProperty() {
257        if (spacing == null) {
258            spacing = new StyleableDoubleProperty() {
259                @Override
260                public void invalidated() {
261                    requestLayout();
262                }
263
264                @Override
265                public CssMetaData getCssMetaData () {
266                    return StyleableProperties.SPACING;
267                }
268
269                @Override
270                public Object getBean() {
271                    return HBox.this;
272                }
273
274                @Override
275                public String getName() {
276                    return "spacing";
277                }
278            };
279        }
280        return spacing;
281    }
282
283    private DoubleProperty spacing;
284    public final void setSpacing(double value) { spacingProperty().set(value); }
285    public final double getSpacing() { return spacing == null ? 0 : spacing.get(); }
286
287    /**
288     * The overall alignment of children within the hbox's width and height.
289     * If the vertical alignment value is BASELINE, then children will always be
290     * resized to their preferred heights and the fillHeight property will be
291     * ignored.
292     */
293    public final ObjectProperty<Pos> alignmentProperty() {
294        if (alignment == null) {
295            alignment = new StyleableObjectProperty<Pos>(Pos.TOP_LEFT) {
296                @Override
297                public void invalidated() {
298                    requestLayout();
299                }
300
301                @Override
302                public CssMetaData<HBox, Pos> getCssMetaData() {
303                    return StyleableProperties.ALIGNMENT;
304                }
305
306                @Override
307                public Object getBean() {
308                    return HBox.this;
309                }
310
311                @Override
312                public String getName() {
313                    return "alignment";
314                }
315            };
316        }
317        return alignment;
318    }
319
320    private ObjectProperty<Pos> alignment;
321    public final void setAlignment(Pos value) { alignmentProperty().set(value); }
322    public final Pos getAlignment() { return alignment == null ? Pos.TOP_LEFT : alignment.get(); }
323    private Pos getAlignmentInternal() {
324        Pos localPos = getAlignment();
325        return localPos == null ? Pos.TOP_LEFT : localPos;
326    }
327
328    /**
329     * Whether or not resizable children will be resized to fill the full height of the hbox
330     * or be kept to their preferred height and aligned according to the <code>alignment</code>
331     * vpos value.   Note that if the hbox vertical alignment is set to BASELINE, then this
332     * property will be ignored and children will be resized to their preferred heights.
333     */
334    public final BooleanProperty fillHeightProperty() {
335        if (fillHeight == null) {
336            fillHeight = new StyleableBooleanProperty(true) {
337                @Override
338                public void invalidated() {
339                    requestLayout();
340                }
341
342                @Override
343                public CssMetaData<HBox, Boolean> getCssMetaData() {
344                    return StyleableProperties.FILL_HEIGHT;
345                }
346
347                @Override
348                public Object getBean() {
349                    return HBox.this;
350                }
351
352                @Override
353                public String getName() {
354                    return "fillHeight";
355                }
356            };
357        }
358        return fillHeight;
359    }
360
361    private BooleanProperty fillHeight;
362    public final void setFillHeight(boolean value) { fillHeightProperty().set(value); }
363    public final boolean isFillHeight() { return fillHeight == null ? true : fillHeight.get(); }
364
365    private boolean shouldFillHeight() {
366        return isFillHeight() && getAlignmentInternal().getVpos() != VPos.BASELINE;
367    }
368
369    /**
370     *
371     * @return null unless one of its children has a content bias.
372     */
373    @Override public Orientation getContentBias() {
374        if (biasDirty) {
375            final List<Node> children = getChildren();
376            for (Node child : children) {
377                Orientation contentBias = child.getContentBias();
378                if (child.isManaged() && contentBias != null) {
379                    bias = contentBias;
380                    break;
381                }
382            }
383            biasDirty = false;
384        }        
385        return bias;
386    }
387
388    @Override protected double computeMinWidth(double height) {
389        Insets insets = getInsets();
390        return snapSpace(insets.getLeft()) +
391               computeContentWidth(getAreaWidths(getManagedChildren(), height, true)) +
392               snapSpace(insets.getRight());
393    }
394
395    @Override protected double computeMinHeight(double width) {
396        Insets insets = getInsets();
397        List<Node>managed = getManagedChildren();
398        double contentHeight = 0;
399        if (getContentBias() == Orientation.HORIZONTAL) {
400            // if width is different than preferred, then child widths may grow or shrink,
401            // altering the height of any child with a horizontal contentBias.
402            double prefWidths[] = getAreaWidths(managed, -1, false);
403            adjustAreaWidths(managed, prefWidths, width, -1);
404            contentHeight = computeMaxMinAreaHeight(managed, getMargins(managed), prefWidths, getAlignmentInternal().getVpos());
405        } else {
406            contentHeight = computeMaxMinAreaHeight(managed, getMargins(managed), getAlignmentInternal().getVpos());
407        }
408        return snapSpace(insets.getTop()) +
409               contentHeight +
410               snapSpace(insets.getBottom());
411    }
412
413    @Override protected double computePrefWidth(double height) {
414         Insets insets = getInsets();
415         return snapSpace(insets.getLeft()) +
416                computeContentWidth(getAreaWidths(getManagedChildren(), height, false)) +
417                snapSpace(insets.getRight());
418    }
419
420    @Override protected double computePrefHeight(double width) {
421        Insets insets = getInsets();
422        List<Node>managed = getManagedChildren();
423        double contentHeight = 0;
424        if (getContentBias() == Orientation.HORIZONTAL) {
425            // if width is different than preferred, then child widths may grow or shrink,
426            // altering the height of any child with a horizontal contentBias.
427            double prefWidths[] = getAreaWidths(managed, -1, false);
428            adjustAreaWidths(managed, prefWidths, width, -1);
429            contentHeight = computeMaxPrefAreaHeight(managed, getMargins(managed), prefWidths, getAlignmentInternal().getVpos());
430        } else {
431            contentHeight = computeMaxPrefAreaHeight(managed, getMargins(managed), getAlignmentInternal().getVpos());
432        }
433        return snapSpace(insets.getTop()) +
434               contentHeight +
435               snapSpace(insets.getBottom());
436    }
437
438    private Insets[] getMargins(List<Node>managed) {
439        Insets margins[] = new Insets[managed.size()];
440        for(int i = 0; i < margins.length; i++) {
441            margins[i] = getMargin(managed.get(i));
442        }
443        return margins;
444    }
445
446    private double[] getAreaWidths(List<Node>managed, double height, boolean minimum) {
447        // height could be -1
448        double[] prefAreaWidths = new double [managed.size()];
449        final double insideHeight = height == -1? -1 : height -
450                                     snapSpace(getInsets().getTop()) - snapSpace(getInsets().getBottom());
451        for (int i = 0, size = managed.size(); i < size; i++) {
452            Node child = managed.get(i);
453            Insets margin = getMargin(child);
454            prefAreaWidths[i] = minimum?
455                               computeChildMinAreaWidth(child, margin,
456                                   shouldFillHeight()? insideHeight : child.minHeight(-1)) :
457                                   computeChildPrefAreaWidth(child, margin,
458                                       shouldFillHeight()? insideHeight : child.prefHeight(-1));
459        }
460        return prefAreaWidths;
461    }
462
463    private double adjustAreaWidths(List<Node>managed, double areaWidths[], double width, double height) {
464        Insets insets = getInsets();
465        double top = snapSpace(insets.getTop());
466        double bottom = snapSpace(insets.getBottom());
467
468        double contentWidth = computeContentWidth(areaWidths);
469        double extraWidth = (width == -1? prefWidth(-1) : width) -
470                snapSpace(insets.getLeft()) - snapSpace(insets.getRight()) - contentWidth;
471
472        if (extraWidth != 0) {
473            double remaining = growOrShrinkAreaWidths(managed, areaWidths, Priority.ALWAYS, extraWidth,
474                    shouldFillHeight() && height != -1? height - top - bottom : -1);
475            remaining = growOrShrinkAreaWidths(managed, areaWidths, Priority.SOMETIMES, remaining,
476                    shouldFillHeight() && height != -1? height - top - bottom : -1);
477            contentWidth += (extraWidth - remaining);
478        }
479        return contentWidth;
480    }
481
482    private double growOrShrinkAreaWidths(List<Node>managed, double areaWidths[], Priority priority, double extraWidth, double height) {
483        final boolean shrinking = extraWidth < 0;
484        List<Node> adjustList = new ArrayList<Node>();
485        List<Node> adjusting = new ArrayList<Node>();
486
487        for (int i = 0, size = managed.size(); i < size; i++) {
488            final Node child = managed.get(i);
489            if (shrinking || getHgrow(child) == priority) {
490                adjustList.add(child);
491                adjusting.add(child);
492            }
493        }
494
495        double[] areaLimitWidths = new double[adjustList.size()];
496        for (int i = 0, size = adjustList.size(); i < size; i++) {
497            final Node child = adjustList.get(i);
498            final Insets margin = getMargin(child);
499            areaLimitWidths[i] = shrinking?
500                computeChildMinAreaWidth(child, margin, height) : computeChildMaxAreaWidth(child, margin, height);
501        }
502
503        double available = extraWidth; // will be negative in shrinking case
504        while (Math.abs(available) > 1.0 && adjusting.size() > 0) {
505            Node[] adjusted = new Node[adjustList.size()];
506            final double portion = available / adjusting.size(); // negative in shrinking case
507            for (int i = 0, size = adjusting.size(); i < size; i++) {
508                final Node child = adjusting.get(i);
509                final int childIndex = managed.indexOf(child);
510                final double limit = areaLimitWidths[adjustList.indexOf(child)] - areaWidths[childIndex]; // negative in shrinking case
511                final double change = Math.abs(limit) <= Math.abs(portion)? limit : portion;
512                areaWidths[childIndex] += change;
513                //if (node.id.startsWith("debug.")) println("{if (shrinking) "shrink" else "grow"}: {node.id} portion({portion})=available({available})/({sizeof adjusting}) change={change}");
514                available -= change;
515                if (Math.abs(change) < Math.abs(portion)) {
516                    adjusted[i] = child;
517                }
518            }
519            for (int i = 0; i < adjusted.length; i++) {
520                Node node = adjusted[i];
521                if (node != null) {
522                    adjusting.remove(node);
523                }
524            }
525        }
526        for (int i = 0; i < areaWidths.length; i++) {
527            areaWidths[i] = snapSpace(areaWidths[i]);
528        }
529        return available; // might be negative in shrinking case
530    }
531
532    private double computeContentWidth(double[] widths) {
533        double total = 0;
534        for (double w : widths) {
535            total += w;
536        }
537        return total + (widths.length-1)*snapSpace(getSpacing());
538    }
539
540    private double[] actualAreaWidths;
541
542    @Override public void requestLayout() {
543        if (performingLayout) {
544            return;
545        }
546        biasDirty = true;
547        bias = null;
548        super.requestLayout();
549    }
550
551    @Override protected void layoutChildren() {
552        performingLayout = true;
553        List<Node> managed = getManagedChildren();
554        Insets insets = getInsets();
555        Pos align = getAlignmentInternal();
556        HPos alignHpos = align.getHpos();
557        VPos alignVpos = align.getVpos();
558        double width = getWidth();
559        double height = getHeight();
560        double top = snapSpace(insets.getTop());
561        double left = snapSpace(insets.getLeft());
562        double bottom = snapSpace(insets.getBottom());
563        double right = snapSpace(insets.getRight());
564        double space = snapSpace(getSpacing());
565        boolean shouldFillHeight = shouldFillHeight();
566
567        actualAreaWidths = getAreaWidths(managed, height, false);
568        double contentWidth = adjustAreaWidths(managed, actualAreaWidths, width, height);
569        double contentHeight = height - top - bottom;
570
571        double x = snapSpace(insets.getLeft()) + computeXOffset(width - left - right, contentWidth, align.getHpos());
572        double y = snapSpace(insets.getTop());
573        double baselineOffset = alignVpos == VPos.BASELINE ? getMaxBaselineOffset(managed)
574                                    : height/2;
575
576        for (int i = 0, size = managed.size(); i < size; i++) {
577            Node child = managed.get(i);
578            Insets margin = getMargin(child);
579            layoutInArea(child, x, y, actualAreaWidths[i], contentHeight,
580                    baselineOffset, margin, true, shouldFillHeight,
581                    alignHpos, alignVpos);
582            x += actualAreaWidths[i] + space;
583        }
584        performingLayout = false;
585    }
586
587
588    /***************************************************************************
589     *                                                                         *
590     *                         Stylesheet Handling                             *
591     *                                                                         *
592     **************************************************************************/
593
594     /**
595      * Super-lazy instantiation pattern from Bill Pugh.
596      * @treatAsPrivate implementation detail
597      */
598     private static class StyleableProperties {
599
600         private static final CssMetaData<HBox,Pos> ALIGNMENT =
601             new CssMetaData<HBox,Pos>("-fx-alignment",
602                 new EnumConverter<Pos>(Pos.class),
603                 Pos.TOP_LEFT) {
604
605            @Override
606            public boolean isSettable(HBox node) {
607                return node.alignment == null || !node.alignment.isBound();
608            }
609
610            @Override
611            public StyleableProperty<Pos> getStyleableProperty(HBox node) {
612                return (StyleableProperty<Pos>)node.alignmentProperty();
613            }
614
615         };
616
617         private static final CssMetaData<HBox,Boolean> FILL_HEIGHT =
618             new CssMetaData<HBox,Boolean>("-fx-fill-height",
619                 BooleanConverter.getInstance(), Boolean.TRUE) {
620
621            @Override
622            public boolean isSettable(HBox node) {
623                return node.fillHeight == null ||
624                        !node.fillHeight.isBound();
625            }
626
627            @Override
628            public StyleableProperty<Boolean> getStyleableProperty(HBox node) {
629                return (StyleableProperty<Boolean>)node.fillHeightProperty();
630            }
631
632         };
633
634         private static final CssMetaData<HBox,Number> SPACING =
635             new CssMetaData<HBox,Number>("-fx-spacing",
636                 SizeConverter.getInstance(), 0.0){
637
638            @Override
639            public boolean isSettable(HBox node) {
640                return node.spacing == null || !node.spacing.isBound();
641            }
642
643            @Override
644            public StyleableProperty<Number> getStyleableProperty(HBox node) {
645                return (StyleableProperty<Number>)node.spacingProperty();
646            }
647
648         };
649
650         private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
651         static {
652            final List<CssMetaData<? extends Styleable, ?>> styleables =
653                new ArrayList<CssMetaData<? extends Styleable, ?>>(Pane.getClassCssMetaData());
654            styleables.add(FILL_HEIGHT);
655            styleables.add(ALIGNMENT);
656            styleables.add(SPACING);
657            STYLEABLES = Collections.unmodifiableList(styleables);
658         }
659    }
660
661    /**
662     * @return The CssMetaData associated with this class, which may include the
663     * CssMetaData of its super classes.
664     */
665    public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
666        return StyleableProperties.STYLEABLES;
667    }
668
669    /**
670     * {@inheritDoc}
671     *
672     */
673
674
675    @Override
676    public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
677        return getClassCssMetaData();
678    }
679
680}