001package polaris.sdk.ui.controls; 002import polaris.sdk.ui.*; 003 004import java.util.*; 005import java.util.function.BiConsumer; 006public class PropertyGrid extends ScrollPane { 007 private static final class PropertyLabel extends Label { 008 PropertyLabel(String text){super(text);} 009 @Override protected void paint(Painter p){p.text(text,ax,ay+(h-size)/2,size,ink());} 010 } 011 private final java.util.Map<String,Object> values=new LinkedHashMap<String,Object>();private BiConsumer<String,Object> listener; 012 public PropertyGrid(){w=360;h=210;} 013 public PropertyGrid onPropertyChange(BiConsumer<String,Object> c){listener=c;return this;}public Map<String,Object> values(){return Collections.unmodifiableMap(values);} 014 public PropertyGrid property(String name,Object value){if(values.containsKey(name))throw new IllegalArgumentException("Duplicate property "+name);values.put(name,value);Label label=new PropertyLabel(name);label.bounds(12,12+(values.size()-1)*45,130,28);add(label);Widget editor; 015 if(value instanceof Boolean){Switch box=new Switch("");box.selected((Boolean)value);box.onChange(w->update(name,box.selected()));editor=box;} 016 else if(value instanceof Number){NumberField number=new NumberField(((Number)value).doubleValue());number.onChange(w->update(name,number.number()));editor=number;} 017 else {TextField text=new TextField(String.valueOf(value));text.onChange(w->update(name,text.value()));editor=text;} 018 editor.bounds(145,8+(values.size()-1)*45,Math.max(80,w-165),34);add(editor);return this; 019 } 020 private void update(String name,Object value){values.put(name,value);changed();if(listener!=null)listener.accept(name,value);} 021 @Override protected void layoutChildren(){ 022 float content=Math.max(0,w-2*padding),labelWidth=Math.max(0,(content-gap)*.40f); 023 for(int i=0;i<children.size();i++){ 024 Widget c=children.get(i);float yy=padding+(i/2)*(Spacing.CONTROL_HEIGHT+gap); 025 c.bounds(i%2==0?padding:padding+labelWidth+gap,yy, 026 i%2==0?labelWidth:Math.max(0,content-labelWidth-gap),Spacing.CONTROL_HEIGHT); 027 } 028 super.layoutChildren(); 029 } 030}