add grid layout support

This commit is contained in:
Dmitry Abramov 2009-02-03 10:36:20 +00:00
parent e403f6e4e3
commit 0a33a49aff
20 changed files with 354 additions and 35 deletions

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
* Author: Dmitry Abramov
* Created: 03.02.2009 13:01:37
* $Id$
*/
package com.haulmont.cuba.gui.components;
public interface GridLayout extends Component.Container {
void add(Component component, int col, int row);
int getRows();
void setRows(int rows);
int getColumns();
void setColumns(int columns);
}

View File

@ -9,5 +9,9 @@
*/
package com.haulmont.cuba.gui.components;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.CollectionDatasource;
public interface LookupField extends Field {
void setLookupDatasource(CollectionDatasource datasource);
}

View File

@ -13,7 +13,7 @@ import java.util.List;
import java.util.Collection;
public interface Tabsheet extends Component {
void addTab(String name, Component component);
Tab addTab(String name, Component component);
void removeTab(String name);
Tab getTab();
@ -25,5 +25,8 @@ public interface Tabsheet extends Component {
interface Tab {
String getName();
void setName(String name);
String getCaption();
void setCaption(String caption);
}
}

View File

@ -36,13 +36,14 @@ public class LayoutLoaderConfig {
private static void registerComponents(LayoutLoaderConfig config) {
config.registerLoader("hbox", HBoxLoader.class);
config.registerLoader("vbox", VBoxLoader.class);
config.registerLoader("grid", GridLoader.class);
config.registerLoader("button", ButtonLoader.class);
config.registerLoader("group-box", GroupBoxLoader.class);
config.registerLoader("label", LabelLoader.class);
config.registerLoader("text-field", AbstractFieldLoader.class);
config.registerLoader("text-area", AbstractFieldLoader.class);
config.registerLoader("date-field", AbstractFieldLoader.class);
config.registerLoader("lookup-field", AbstractFieldLoader.class);
config.registerLoader("lookup-field", LookupFieldLoader.class);
config.registerLoader("table", TableLoader.class);
config.registerLoader("iframe", IFrameLoader.class);
config.registerLoader("split", SplitPanelLoader.class);

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
* Author: Dmitry Abramov
* Created: 03.02.2009 12:59:26
* $Id$
*/
package com.haulmont.cuba.gui.xml.layout.loaders;
import com.haulmont.cuba.gui.components.Component;
import com.haulmont.cuba.gui.components.GridLayout;
import com.haulmont.cuba.gui.data.DsContext;
import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;
import com.haulmont.cuba.gui.xml.layout.LayoutLoader;
import com.haulmont.cuba.gui.xml.layout.LayoutLoaderConfig;
import org.dom4j.Element;
import java.util.Collection;
import java.util.List;
public class GridLoader extends ContainerLoader implements com.haulmont.cuba.gui.xml.layout.ComponentLoader {
public GridLoader(LayoutLoaderConfig config, ComponentsFactory factory, DsContext dsContext) {
super(config, factory, dsContext);
}
public Component loadComponent(ComponentsFactory factory, Element element) throws InstantiationException, IllegalAccessException {
GridLayout component = factory.createComponent("grid");
loadId(component, element);
final Element columnsElement = element.element("columns");
final Element rowsElement = element.element("rows");
final List<Element> columnElements = columnsElement.elements("column");
component.setColumns(columnElements.size());
final List<Element> rowElements = rowsElement.elements("row");
component.setRows(rowElements.size());
int row = 0;
for (Element rowElement : rowElements) {
loadSubComponents(component, rowElement, row);
row++;
}
return component;
}
protected void loadSubComponents(GridLayout component, Element element, int row) {
final LayoutLoader loader = new LayoutLoader(factory, config, dsContext);
int col = 0;
for (Element subElement : (Collection<Element>)element.elements()) {
final Component subComponent = loader.loadComponent(subElement);
component.add(subComponent, col, row);
col++;
}
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
* Author: Dmitry Abramov
* Created: 03.02.2009 11:47:37
* $Id$
*/
package com.haulmont.cuba.gui.xml.layout.loaders;
import com.haulmont.cuba.gui.xml.layout.LayoutLoaderConfig;
import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;
import com.haulmont.cuba.gui.data.DsContext;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.CollectionDatasource;
import com.haulmont.cuba.gui.components.Component;
import com.haulmont.cuba.gui.components.LookupField;
import org.dom4j.Element;
import org.apache.commons.lang.StringUtils;
public class LookupFieldLoader extends AbstractFieldLoader {
public LookupFieldLoader(LayoutLoaderConfig config, ComponentsFactory factory, DsContext dsContext) {
super(config, factory, dsContext);
}
@Override
public Component loadComponent(ComponentsFactory factory, Element element) throws InstantiationException, IllegalAccessException {
final LookupField component = (LookupField) super.loadComponent(factory, element);
final String datasource = element.attributeValue("lookupDatasource");
if (!StringUtils.isEmpty(datasource)) {
final Datasource ds = dsContext.get(datasource);
component.setLookupDatasource((CollectionDatasource) ds);
}
return component;
}
}

View File

@ -15,6 +15,7 @@ import com.haulmont.cuba.gui.data.DsContext;
import com.haulmont.cuba.gui.xml.layout.ComponentLoader;
import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;
import com.haulmont.cuba.gui.xml.layout.LayoutLoaderConfig;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Element;
import java.util.List;
@ -32,10 +33,19 @@ public class TabsheetLoader extends ContainerLoader {
final List<Element> tabElements = element.elements("tab");
for (Element tabElement : tabElements) {
final String name = tabElement.attributeValue("name");
final String name = tabElement.attributeValue("id");
final ComponentLoader loader = getLoader("vbox");
component.addTab(name, loader.loadComponent(factory, tabElement));
final Tabsheet.Tab tab = component.addTab(name, loader.loadComponent(factory, tabElement));
String caption = tabElement.attributeValue("caption");
if (!StringUtils.isEmpty(caption)) {
if (caption.startsWith("res://") && resourceBundle != null) {
caption = resourceBundle.getString(caption.substring(6));
}
tab.setCaption(caption);
}
}
return component;

View File

@ -3,4 +3,7 @@
<property name="name"/>
<property name="login"/>
</view>
<view entity="sec$Group" name="lookup">
<property name="name"/>
</view>
</views>

View File

@ -12,18 +12,42 @@
class="com.haulmont.cuba.security.entity.User"
view="edit"
/>
<collection-datasource
id="groups"
class="com.haulmont.cuba.security.entity.Group"
view="lookup"
>
<query>select g from sec$Group g</query>
</collection-datasource>
</dsContext>
<layout>
<hbox>
<vbox>
<label value="Name"/>
<label value="Login"/>
</vbox>
<vbox>
<text-field id="name" datasource="user" property="name"/>
<text-field id="login" datasource="user" property="login"/>
</vbox>
</hbox>
<tabsheet>
<tab id="general" caption="General">
<grid>
<columns>
<column/>
<column/>
</columns>
<rows>
<row>
<label value="Name"/>
<text-field id="name" datasource="user" property="name"/>
</row>
<row>
<label value="Login"/>
<hbox>
<text-field id="login" datasource="user" property="login"/>
<button caption="Browse..."/>
</hbox>
</row>
</rows>
</grid>
</tab>
<tab id="additional" caption="Additional">
<lookup-field id="groups" lookupDatasource="groups"/>
</tab>
</tabsheet>
</layout>
</window>

View File

@ -23,6 +23,10 @@ public class AbstractPanel extends Panel implements com.haulmont.cuba.gui.compon
private String id;
private Component component;
public AbstractPanel() {
setStyleName(Panel.STYLE_LIGHT);
}
public void add(Component component) {
final com.itmill.toolkit.ui.Component comp = ComponentsHelper.unwrap(component);
if (comp instanceof Layout) {

View File

@ -13,8 +13,8 @@ import com.haulmont.cuba.gui.components.Component;
import com.itmill.toolkit.ui.ExpandLayout;
import org.apache.commons.lang.StringUtils;
public class ExpandableHBox extends AbstractExpandableContainer implements com.haulmont.cuba.gui.components.OrderedLayout {
public ExpandableHBox() {
public class ExpandableHBoxLayout extends AbstractExpandableContainer implements com.haulmont.cuba.gui.components.OrderedLayout {
public ExpandableHBoxLayout() {
super(ExpandLayout.ORIENTATION_HORIZONTAL);
}
}

View File

@ -13,9 +13,9 @@ import com.haulmont.cuba.gui.components.Component;
import com.itmill.toolkit.ui.ExpandLayout;
import org.apache.commons.lang.StringUtils;
public class ExpandableVBox extends AbstractExpandableContainer implements com.haulmont.cuba.gui.components.OrderedLayout {
public class ExpandableVBoxLayout extends AbstractExpandableContainer implements com.haulmont.cuba.gui.components.OrderedLayout {
public ExpandableVBox() {
public ExpandableVBoxLayout() {
super(ExpandLayout.ORIENTATION_VERTICAL);
}
}

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2008 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
* Author: Dmitry Abramov
* Created: 03.02.2009 13:11:34
* $Id$
*/
package com.haulmont.cuba.web.components;
import com.haulmont.cuba.gui.components.Component;
import com.itmill.toolkit.ui.Layout;
import java.util.HashMap;
import java.util.Map;
public class GridLayout extends com.itmill.toolkit.ui.GridLayout implements com.haulmont.cuba.gui.components.GridLayout {
private int verticalAlignment = Layout.AlignmentHandler.ALIGNMENT_TOP;
private int horizontalAlignment = Layout.AlignmentHandler.ALIGNMENT_LEFT;
protected String id;
protected Map<String, Component> componentByIds = new HashMap<String, Component>();
public void add(Component component) {
final com.itmill.toolkit.ui.Component itmillComponent = ComponentsHelper.unwrap(component);
addComponent(itmillComponent);
setComponentAlignment(itmillComponent, component.getHorizontalAlignment(), component.getVerticalAlignment());
if (component.getId() != null) {
componentByIds.put(component.getId(), component);
}
}
public void add(Component component, int col, int row) {
final com.itmill.toolkit.ui.Component itmillComponent = ComponentsHelper.unwrap(component);
addComponent(itmillComponent, col, row);
setComponentAlignment(itmillComponent, component.getHorizontalAlignment(), component.getVerticalAlignment());
if (component.getId() != null) {
componentByIds.put(component.getId(), component);
}
}
public void remove(Component component) {
removeComponent(ComponentsHelper.unwrap(component));
if (component.getId() != null) {
componentByIds.remove(component.getId());
}
}
public <T extends Component> T getOwnComponent(String id) {
return (T) componentByIds.get(id);
}
public <T extends Component> T getComponent(String id) {
return ComponentsHelper.<T>getComponent(this, id);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void requestFocus() {
}
public int getVerticalAlignment() {
return verticalAlignment;
}
public void setVerticalAlignment(int verticalAlIlignment) {
this.verticalAlignment = verticalAlIlignment;
final com.itmill.toolkit.ui.Component component = getParent();
if (component instanceof AlignmentHandler) {
((AlignmentHandler) component).setComponentAlignment(this, horizontalAlignment, verticalAlIlignment);
}
}
public int getHorizontalAlignment() {
return horizontalAlignment;
}
public void setHorizontalAlignment(int horizontalAlIlignment) {
this.horizontalAlignment = horizontalAlIlignment;
final com.itmill.toolkit.ui.Component component = getParent();
if (component instanceof AlignmentHandler) {
((AlignmentHandler) component).setComponentAlignment(this, horizontalAlIlignment, verticalAlignment);
}
}
}

View File

@ -24,5 +24,6 @@ public class GroupBox extends AbstractPanel implements Component.HasCaption {
public GroupBox() {
setLayout(new ExpandLayout(OrderedLayout.ORIENTATION_VERTICAL));
setStyleName(Panel.STYLE_EMPHASIZE);
}
}

View File

@ -12,8 +12,8 @@ package com.haulmont.cuba.web.components;
import com.haulmont.cuba.gui.components.Component;
import com.itmill.toolkit.ui.ExpandLayout;
public class HBox extends AbstractContainer implements com.haulmont.cuba.gui.components.OrderedLayout {
public HBox() {
public class HBoxLayout extends AbstractContainer implements com.haulmont.cuba.gui.components.OrderedLayout {
public HBoxLayout() {
super(ExpandLayout.ORIENTATION_HORIZONTAL);
}

View File

@ -10,6 +10,9 @@
package com.haulmont.cuba.web.components;
import com.haulmont.cuba.gui.components.Component;
import com.haulmont.cuba.gui.data.Datasource;
import com.haulmont.cuba.gui.data.CollectionDatasource;
import com.haulmont.cuba.web.data.CollectionDatasourceWrapper;
import com.itmill.toolkit.ui.Select;
public class LookupField
@ -22,4 +25,8 @@ public class LookupField
this.component = new Select();
component.setImmediate(true);
}
public void setLookupDatasource(CollectionDatasource datasource) {
component.setContainerDataSource(new CollectionDatasourceWrapper(datasource, true));
}
}

View File

@ -46,16 +46,28 @@ public class Tabsheet
this.name = name;
}
public String getCaption() {
return Tabsheet.this.component.getTabCaption(ComponentsHelper.unwrap(component));
}
public void setCaption(String caption) {
Tabsheet.this.component.setTabCaption(ComponentsHelper.unwrap(component), caption);
}
public Component getComponent() {
return component;
}
}
public void addTab(String name, Component component) {
this.tabs.put(name, new Tab(name, component));
public com.haulmont.cuba.gui.components.Tabsheet.Tab addTab(String name, Component component) {
final Tab tab = new Tab(name, component);
this.tabs.put(name, tab);
this.components.put(component, name);
this.component.addTab(ComponentsHelper.unwrap(component));
return tab;
}
public void removeTab(String name) {

View File

@ -12,9 +12,9 @@ package com.haulmont.cuba.web.components;
import com.haulmont.cuba.gui.components.Component;
import com.itmill.toolkit.ui.ExpandLayout;
public class VBox extends AbstractContainer implements com.haulmont.cuba.gui.components.OrderedLayout {
public class VBoxLayout extends AbstractContainer implements com.haulmont.cuba.gui.components.OrderedLayout {
public VBox() {
public VBoxLayout() {
super(ExpandLayout.ORIENTATION_VERTICAL);
}

View File

@ -26,13 +26,22 @@ import java.util.*;
public class CollectionDatasourceWrapper implements Container, Container.ItemSetChangeNotifier {
protected CollectionDatasource datasource;
private Collection<MetaProperty> properties = new ArrayList<MetaProperty>();
protected boolean autoRefresh;
protected boolean ignoreListeners;
protected CollectionDatasource datasource;
private Collection<MetaProperty> properties = new ArrayList<MetaProperty>();
private List<ItemSetChangeListener> itemSetChangeListeners = new ArrayList<ItemSetChangeListener>();
public CollectionDatasourceWrapper(CollectionDatasource datasource) {
this(datasource, false);
}
public CollectionDatasourceWrapper(CollectionDatasource datasource, boolean autoRefresh) {
this.datasource = datasource;
this.autoRefresh = autoRefresh;
final View view = datasource.getView();
final MetaClass metaClass = datasource.getMetaClass();
@ -67,18 +76,30 @@ public class CollectionDatasourceWrapper implements Container, Container.ItemSet
public void itemChanged(Datasource ds, Object prevItem, Object item) {}
public void stateChanged(Datasource ds, Datasource.State prevState, Datasource.State state) {
fireItemSetChanged();
final boolean prevIgnoreListeners = ignoreListeners;
try {
fireItemSetChanged();
} finally {
ignoreListeners = prevIgnoreListeners;
}
}
public void valueChanged(Object source, String property, Object prevValue, Object value) {}
public void collectionChanged(Datasource ds, CollectionOperation operation) {
fireItemSetChanged();
final boolean prevIgnoreListeners = ignoreListeners;
try {
fireItemSetChanged();
} finally {
ignoreListeners = prevIgnoreListeners;
}
}
});
}
protected void fireItemSetChanged() {
if (ignoreListeners) return;
for (ItemSetChangeListener listener : itemSetChangeListeners) {
listener.containerItemSetChange(new ItemSetChangeEvent() {
public Container getContainer() {
@ -109,7 +130,8 @@ public class CollectionDatasourceWrapper implements Container, Container.ItemSet
return properties;
}
public Collection getItemIds() {
public synchronized Collection getItemIds() {
__autoRefreshInvalid();
return datasource.getItemIds();
}
@ -123,11 +145,13 @@ public class CollectionDatasourceWrapper implements Container, Container.ItemSet
return MetadataHelper.getPropertyTypeClass(metaProperty);
}
public int size() {
public synchronized int size() {
__autoRefreshInvalid();
return datasource.size();
}
public boolean containsId(Object itemId) {
public synchronized boolean containsId(Object itemId) {
__autoRefreshInvalid();
return datasource.containsItem(itemId);
}
@ -162,4 +186,10 @@ public class CollectionDatasourceWrapper implements Container, Container.ItemSet
public void removeListener(ItemSetChangeListener listener) {
this.itemSetChangeListeners.remove(listener);
}
protected void __autoRefreshInvalid() {
if (autoRefresh && Datasource.State.INVALID.equals(datasource.getState())) {
datasource.refresh();
}
}
}

View File

@ -24,10 +24,13 @@ public class WebComponentsFactory implements ComponentsFactory {
static {
classes.put("window", Window.class);
classes.put("window.editor", Window.Editor.class);
classes.put("hbox", HBox.class);
classes.put("vbox", VBox.class);
classes.put("expandable-hbox", ExpandableHBox.class);
classes.put("expandable-vbox", ExpandableVBox.class);
classes.put("hbox", HBoxLayout.class);
classes.put("vbox", VBoxLayout.class);
classes.put("expandable-hbox", ExpandableHBoxLayout.class);
classes.put("expandable-vbox", ExpandableVBoxLayout.class);
classes.put("grid", GridLayout.class);
classes.put("button", Button.class);
classes.put("label", Label.class);
classes.put("group-box", GroupBox.class);