com.codename1.ui.InterFormContainer Maven / Gradle / Ivy
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codename1.ui;
import static com.codename1.ui.ComponentSelector.$;
import com.codename1.ui.ComponentSelector.Filter;
import com.codename1.ui.geom.Dimension;
import com.codename1.ui.layouts.BorderLayout;
import java.util.HashMap;
import java.util.Map;
/**
* A container that allows you to use the same component on multiple forms. This is most
* useful for adding a global footer or sidebar that appears on multiple forms, or even the
* whole app. For example, the Twitter app has tabs for "Home", "Search", "Messages", etc.. that
* are always shown in the app, and are fixed in place, even between forms. This container
* allows you to achieve a similar thing with Codename One apps.
*
* Note that the InterFormContainer object itself cannot be added to multiple forms. You
* need to create two InterFormContainer instances that share the same content.
* @since 7.0
* @author shannah
*/
public class InterFormContainer extends Container {
private Component content;
/**
* Creates an interform container with the provided content.
* @param content The component that is to be shared across multiple forms.
*/
public InterFormContainer(Component content) {
this.content = content;
setLayout(new BorderLayout());
$(this).selectAllStyles().setPadding(0).setMargin(0);
}
/**
* {@inheritDoc}
*/
@Override
protected void initComponent() {
if (content.getParent() != this) {
content.remove();
add(CENTER, content);
}
super.initComponent();
}
/**
* Finds any InterformContainer instances in the UI hierarchy rooted at {@literal root}
* that contains the same content as this container.
* @param root A component/container whose UI hierarchy is to be searched.
* @return An InterFormContainer with the same content as this container, or null if none is found.
*/
public InterFormContainer findPeer(Component root) {
if (root.getClass() == InterFormContainer.class) {
InterFormContainer cnt = (InterFormContainer)root;
if (cnt.content == content) {
return cnt;
}
}
if (root instanceof Container) {
Container cnt = (Container)root;
int len = cnt.getComponentCount();
for (int i=0; i findCommonContainers(Component root1, Component root2) {
final Map set1 = new HashMap();
final Map set2 = new HashMap();
final Map out = new HashMap();
ComponentSelector.select("*", root1).filter(new Filter() {
@Override
public boolean filter(Component c) {
if (c.getClass() == InterFormContainer.class) {
set1.put(((InterFormContainer)c).content, (InterFormContainer)c);
return true;
}
return false;
}
});
ComponentSelector.select("*", root2).filter(new Filter() {
@Override
public boolean filter(Component c) {
if (c.getClass() == InterFormContainer.class) {
set2.put(((InterFormContainer)c).content, (InterFormContainer)c);
return true;
}
return false;
}
});
for (Component c : set1.keySet()) {
if (set2.containsKey(c)) {
out.put(set1.get(c), set2.get(c));
}
}
return out;
}
/**
* {@inheritDoc}
*/
public void paint(Graphics g) {
if (!isVisible()) {
return;
}
if (content.getParent() != this) {
if (isInitialized() && !content.isInitialized()) {
if (content.getParent() != null) {
content.remove();
}
add(BorderLayout.CENTER, content);
}
}
g.translate(getX() - content.getX(), getY() - content.getY());
content.paintComponentBackground(g);
content.paint(g);
g.translate(content.getX() - getX(), content.getY() - getY());
}
/**
* {@inheritDoc}
*/
@Override
protected Dimension calcPreferredSize() {
return new Dimension(content.getPreferredW() + content.getStyle().getHorizontalMargins(), content.getPreferredH() + content.getStyle().getVerticalMargins());
}
/**
* Injects the given "content" as an InterFormContainer inside the component hierarchy
* rooted at "root"
* @param selector A selector to identify the component to add the container to. See {@link ComponentSelector}.
* @param root The root container serving as a starting point for the selector search.
* @param content The content to inject.
* @return The InterFormContainer that was injected, or null if the selector didn't match any containers.
*/
public static InterFormContainer inject(String selector, Container root, Component content) {
for (Component c : $(selector, root)) {
if (c instanceof Container) {
Container slotCnt = (Container)c;
if (!(slotCnt.getLayout() instanceof BorderLayout)) {
slotCnt.setLayout(new BorderLayout());
}
slotCnt.getStyle().stripMarginAndPadding();
slotCnt.removeAll();
InterFormContainer ifc = new InterFormContainer(content);
slotCnt.add(BorderLayout.CENTER, ifc);
return ifc;
}
}
return null;
}
}