// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.client.editor.simple.components;
import com.google.appinventor.client.editor.simple.SimpleEditor;
import com.google.appinventor.client.editor.simple.components.utils.PropertiesUtil;
import com.google.appinventor.client.editor.youngandroid.properties.YoungAndroidHorizontalAlignmentChoicePropertyEditor;
import com.google.appinventor.client.editor.youngandroid.properties.YoungAndroidVerticalAlignmentChoicePropertyEditor;
import com.google.appinventor.client.output.OdeLog;
import com.google.appinventor.client.properties.BadPropertyEditorException;
import com.google.appinventor.components.common.ComponentConstants;
import com.google.gwt.event.dom.client.ErrorEvent;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Image;
import static com.google.appinventor.client.Ode.MESSAGES;
/**
* Superclass for HVArrangement based mock components
*
* @author markf@google.com (Mark Friedman)
* @author sharon@google.com (Sharon Perl)
* @author hal@mit.edu (Hal Abelson) (added adjust alignment dropdowns)
* @author kkashi01@gmail.com (Hossein Amerkashi) (added Image and BackgroundColors)
*/
public class MockHVArrangement extends MockContainer {
//!!! why was this abstract?
// Form UI components
protected final AbsolutePanel layoutWidget;
// Property names
private static final String PROPERTY_NAME_IMAGE = "Image";
private boolean hasImage;
// We need to maintain these so we can show color and shape only when
// there is no image.
private String backgroundColor;
private MockHVLayout myLayout;
private static final String PROPERTY_NAME_HORIZONTAL_ALIGNMENT = "AlignHorizontal";
private static final String PROPERTY_NAME_VERTICAL_ALIGNMENT = "AlignVertical";
private YoungAndroidHorizontalAlignmentChoicePropertyEditor myHAlignmentPropertyEditor;
private YoungAndroidVerticalAlignmentChoicePropertyEditor myVAlignmentPropertyEditor;
private final Image image;
private String imagePropValue;
private boolean scrollAble;
private int orientation;
/**
* Creates a new MockHVArrangement component.
*/
MockHVArrangement(SimpleEditor editor, String type, ImageResource icon, int orientation,
boolean scrollable) {
// Note(Hal): This helper thing is a kludge because I really want to write:
// myLayout = new MockHVLayout(orientation);
// super(editor, type, icon, myLayout);
// but Java won't let me do that.
super(editor, type, icon, MockHVArrangementHelper.makeLayout(orientation));
// Note(hal): There better not be any calls to MockHVArrangementHelper before the
// next instruction. Note that the Helper methods are synchronized to avoid possible
// future problems if we ever have threads creating arrangements in parallel.
myLayout = MockHVArrangementHelper.getLayout();
scrollAble = scrollable;
this.orientation = orientation;
if (orientation != ComponentConstants.LAYOUT_ORIENTATION_VERTICAL &&
orientation != ComponentConstants.LAYOUT_ORIENTATION_HORIZONTAL) {
throw new IllegalArgumentException("Illegal orientation: " + orientation);
}
rootPanel.setHeight("100%");
layoutWidget = new AbsolutePanel();
layoutWidget.setStylePrimaryName("ode-SimpleMockContainer");
layoutWidget.add(rootPanel);
image = new Image();
image.addErrorHandler(new ErrorHandler() {
@Override
public void onError(ErrorEvent event) {
if (imagePropValue != null && !imagePropValue.isEmpty()) {
OdeLog.elog("Error occurred while loading image " + imagePropValue);
}
refreshForm();
}
});
image.addLoadHandler(new LoadHandler() {
@Override
public void onLoad(LoadEvent event) {
refreshForm();
}
});
initComponent(layoutWidget);
try {
myHAlignmentPropertyEditor = PropertiesUtil.getHAlignmentEditor(properties);
myVAlignmentPropertyEditor = PropertiesUtil.getVAlignmentEditor(properties);
} catch (BadPropertyEditorException e) {
OdeLog.log(MESSAGES.badAlignmentPropertyEditorForArrangement());
return;
}
adjustAlignmentDropdowns();
}
@Override
public void onPropertyChange(String propertyName, String newValue) {
super.onPropertyChange(propertyName, newValue);
if (propertyName.equals(PROPERTY_NAME_HORIZONTAL_ALIGNMENT)) {
myLayout.setHAlignmentFlags(newValue);
refreshForm();
} else if (propertyName.equals(PROPERTY_NAME_VERTICAL_ALIGNMENT)) {
myLayout.setVAlignmentFlags(newValue);
refreshForm();
} else if (propertyName.equals(PROPERTY_NAME_IMAGE)) {
setImageProperty(newValue);
refreshForm();
} else if (propertyName.equals(PROPERTY_NAME_BACKGROUNDCOLOR)) {
setBackgroundColorProperty(newValue);
} else {
if (propertyName.equals(PROPERTY_NAME_WIDTH) || propertyName.equals(PROPERTY_NAME_HEIGHT)) {
refreshForm();
}
}
}
private void adjustAlignmentDropdowns() {
if (scrollAble) {
if (orientation == ComponentConstants.LAYOUT_ORIENTATION_VERTICAL) {
myLayout.setVAlignmentFlags(ComponentConstants.GRAVITY_TOP + "");
changeProperty(PROPERTY_NAME_VERTICAL_ALIGNMENT, ComponentConstants.GRAVITY_TOP + "");
myVAlignmentPropertyEditor.disable();
} else {
myLayout.setHAlignmentFlags(ComponentConstants.GRAVITY_LEFT + "");
changeProperty(PROPERTY_NAME_HORIZONTAL_ALIGNMENT, ComponentConstants.GRAVITY_LEFT+ "");
myHAlignmentPropertyEditor.disable();
}
refreshForm();
} else {
myVAlignmentPropertyEditor.enable();
myHAlignmentPropertyEditor.enable();
}
}
/*
* Sets the button's Image property to a new value.
*/
private void setImageProperty(String text) {
imagePropValue = text;
String url = convertImagePropertyValueToUrl(text);
if (url == null) {
hasImage = false;
url = "";
setBackgroundColorProperty(backgroundColor);
} else {
hasImage = true;
// Layouts do not show a background color if they have an image.
// The container's background color shows through any transparent
// portions of the Image, an effect we can get in the browser by
// setting the widget's background color to COLOR_NONE.
MockComponentsUtil.setWidgetBackgroundColor(layoutWidget,
"&H" + COLOR_NONE);
}
MockComponentsUtil.setWidgetBackgroundImage(layoutWidget, url);
image.setUrl(url);
}
/*
* Sets the button's BackgroundColor property to a new value.
*/
private void setBackgroundColorProperty(String text) {
backgroundColor = text;
// Android Buttons do not show a background color if they have an image.
if (hasImage) {
return;
}
if (MockComponentsUtil.isDefaultColor(text)) {
// CSS background-color for ode-SimpleMockButton (copied from Ya.css)
text = "&HFFE8E8E8";
}
MockComponentsUtil.setWidgetBackgroundColor(layoutWidget, text);
}
}