package org.droiddraw.widget; import java.util.Vector; import org.droiddraw.property.Property; import org.droiddraw.property.SelectProperty; import org.droiddraw.property.StringProperty; public class LinearLayout extends AbstractLayout { SelectProperty orientation; SelectProperty gravity; boolean vertical; int max_base; public static int VERTICAL_PADDING = 2; public static int HORIZONTAL_PADDING = 2; int share; private static final String[] OPTIONS = new String[] {"left", "right","center_horizontal", "top", "bottom", "center_vertical"}; public LinearLayout() { this(true); } public LinearLayout(boolean vertical) { super("LinearLayout"); this.orientation = new SelectProperty("Orientation", "android:orientation", new String[] {"horizontal", "vertical"}, 0); this.orientation.setSelectedIndex(1); this.gravity = new SelectProperty("Gravity", "android:gravity", new String[] {"top", "bottom", "left", "right"}, 0); addProperty(orientation); addProperty(gravity); } @Override public void apply() { super.apply(); if (orientation != null) vertical = "vertical".equals(orientation.getStringValue()); } @Override public void addWidget(Widget w) { if (!vertical) { if (! (w instanceof Layout) && w.getBaseline() > max_base) { max_base = w.getBaseline(); } } super.addWidget(w); } @Override public void positionWidget(Widget w) { widgets.remove(w); if (vertical) { int y = w.getY(); if (y >= -100) { int ix = 0; while(ix < widgets.size() && y > widgets.get(ix).getY()) ix++; widgets.add(ix, w); } else { widgets.add(w); } } else { int x = w.getX(); if (x >= 0) { int ix= 0; while (ix < widgets.size() && x > widgets.get(ix).getX()) ix++; widgets.add(ix, w); } else { widgets.add(w); } } repositionAllWidgets(); } @Override public void repositionAllWidgets() { for (Widget w : widgets) { w.apply(); } repositionAllWidgetsInternal(); } protected void repositionAllWidgetsInternal() { int y; int x; Vector<Widget> with_weight = new Vector<Widget>(); int max_base = 0; int max_base_bottom = 0; if (gravity == null) return; String lGrav = gravity.getStringValue(); y = 0; x = 0; for (Widget w : widgets) { if (!vertical) { if (! (w instanceof Layout)) { if (!w.propertyHasValueByAttName("android:layout_gravity", "bottom") || (!gravity.isDefault() && lGrav.equals("bottom"))) { if (w.getBaseline() > max_base) { max_base = w.getBaseline(); } } else { if (w.getHeight()-w.getBaseline() > max_base_bottom) { max_base_bottom = w.getHeight()-w.getBaseline(); } } } } StringProperty prop = (StringProperty)w.getPropertyByAttName("android:layout_weight"); if (prop != null && "1".equals(prop.getStringValue())) with_weight.add(w); if (vertical) y +=w.getPadding(TOP)+w.getHeight()+w.getPadding(BOTTOM)+w.getMargin(TOP)+w.getMargin(BOTTOM); else x += w.getPadding(LEFT)+w.getWidth()+w.getPadding(RIGHT)+w.getMargin(LEFT)+w.getMargin(RIGHT); } int extra=0; if (vertical) { extra = getHeight()-y; } else { extra = getWidth()-x; } if (with_weight.size() > 0) { share = extra/with_weight.size(); System.err.println("Share: " + this + " " + share); } y=0; x=0; for (Widget w : widgets) { String gravity = "left"; StringProperty prop = (StringProperty)w.getPropertyByAttName("android:layout_gravity"); if (prop != null) gravity = prop.getStringValue(); if (vertical) { int width_w_pad = (w.getPadding(Widget.LEFT)+w.getWidth()+w.getPadding(Widget.RIGHT)); if (gravity.contains("right")) x = getWidth()-width_w_pad; else if ("center_horizontal".equals(gravity) || "center".equals(gravity)) x = getWidth()/2-width_w_pad/2; else x = w.getPadding(Widget.LEFT)+w.getMargin(Widget.LEFT); } else { if (gravity.contains("bottom")) y = getHeight()-max_base_bottom-w.getBaseline(); else if ("center_vertical".equals(gravity) || "center".equals(gravity)) y = getHeight()/2-w.getBaseline(); else { if (w instanceof Layout) { y = w.getPadding(Widget.TOP)+w.getMargin(Widget.TOP); } else { y = max_base-w.getBaseline()+w.getPadding(TOP); } } } if (vertical) { y+=w.getPadding(Widget.TOP)+w.getMargin(Widget.TOP); } else { x+=w.getPadding(Widget.LEFT)+w.getMargin(Widget.LEFT); } w.setPosition(x,y); if (with_weight.size() == 0) { if (vertical) { if (lGrav.equals("bottom")) { w.setPosition(x, y+extra); } } else if (lGrav.equals("right")) { w.setPosition(x+extra, y); } } if (vertical) { y+=w.getHeight()+w.getPadding(Widget.BOTTOM)+w.getMargin(Widget.BOTTOM); if (with_weight.contains(w)) { y+=share; } } else { x+=w.getWidth()+w.getPadding(Widget.RIGHT)+w.getMargin(Widget.RIGHT); if (with_weight.contains(w)) { x+=share; } } } } @Override public void resizeForRendering() { boolean vertical = "vertical".equals(orientation.getStringValue()); for (Widget w : widgets) { if (w instanceof Layout) { ((Layout)w).resizeForRendering(); } StringProperty prop = (StringProperty)w.getPropertyByAttName("android:layout_weight"); boolean weight = (prop != null && "1".equals(prop.getStringValue())); if (weight) { if (vertical) w.setSizeInternal(w.getWidth(), w.getHeight()+share); else w.setSizeInternal(w.getWidth()+share, w.getHeight()); } } } public void addOutputProperties(Widget w, Vector<Property> properties) {} public void addEditableProperties(Widget w) { w.addProperty(new StringProperty("Linear Layout Weight", "android:layout_weight", "0")); w.addProperty(new SelectProperty("Layout Gravity", "android:layout_gravity", OPTIONS, 0)); } public void removeEditableProperties(Widget w) { w.removeProperty(new StringProperty("", "android:layout_weight", "")); w.removeProperty(new SelectProperty("", "android:layout_gravity", new String[] {""}, 0)); } }