GraphicalLayoutEditorpublic class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor implements com.android.ide.eclipse.editors.layout.LayoutReloadMonitor.ILayoutReloadListenerGraphical layout editor, based on GEF.
To understand GEF: http://www.ibm.com/developerworks/opensource/library/os-gef/
To understand Drag'n'drop: http://www.eclipse.org/articles/Article-Workbench-DND/drag_drop.html |
Fields Summary |
---|
private static final String | THEME_SEPARATOR | private final LayoutEditor | mLayoutEditorReference to the layout editor | private org.eclipse.core.resources.IFile | mEditedFilereference to the file being edited. | private org.eclipse.swt.dnd.Clipboard | mClipboard | private org.eclipse.swt.widgets.Composite | mParent | private org.eclipse.gef.palette.PaletteRoot | mPaletteRoot | private org.eclipse.swt.widgets.Text | mCountry | private org.eclipse.swt.widgets.Text | mNetwork | private org.eclipse.swt.widgets.Combo | mLanguage | private org.eclipse.swt.widgets.Combo | mRegion | private org.eclipse.swt.widgets.Combo | mOrientation | private org.eclipse.swt.widgets.Text | mDensity | private org.eclipse.swt.widgets.Combo | mTouch | private org.eclipse.swt.widgets.Combo | mKeyboard | private org.eclipse.swt.widgets.Combo | mTextInput | private org.eclipse.swt.widgets.Combo | mNavigation | private org.eclipse.swt.widgets.Text | mSize1 | private org.eclipse.swt.widgets.Text | mSize2 | private org.eclipse.swt.widgets.Combo | mThemeCombo | private org.eclipse.swt.widgets.Button | mCreateButton | private org.eclipse.swt.widgets.Label | mCountryIcon | private org.eclipse.swt.widgets.Label | mNetworkIcon | private org.eclipse.swt.widgets.Label | mLanguageIcon | private org.eclipse.swt.widgets.Label | mRegionIcon | private org.eclipse.swt.widgets.Label | mOrientationIcon | private org.eclipse.swt.widgets.Label | mDensityIcon | private org.eclipse.swt.widgets.Label | mTouchIcon | private org.eclipse.swt.widgets.Label | mKeyboardIcon | private org.eclipse.swt.widgets.Label | mTextInputIcon | private org.eclipse.swt.widgets.Label | mNavigationIcon | private org.eclipse.swt.widgets.Label | mSizeIcon | private org.eclipse.swt.widgets.Label | mCurrentLayoutLabel | private org.eclipse.swt.graphics.Image | mWarningImage | private org.eclipse.swt.graphics.Image | mMatchImage | private org.eclipse.swt.graphics.Image | mErrorImage | private com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration | mCurrentConfigThe {@link FolderConfiguration} representing the state of the UI controls | private com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration | mEditedConfigThe {@link FolderConfiguration} being edited. | private Map | mConfiguredFrameworkRes | private Map | mConfiguredProjectRes | private ProjectCallback | mProjectCallback | private com.android.layoutlib.api.ILayoutLog | mLogger | private boolean | mNeedsXmlReload | private boolean | mNeedsRecompute | private int | mPlatformThemeCount | private boolean | mDisableUpdates | private com.android.ide.eclipse.adt.sdk.Sdk.ITargetChangeListener | mTargetListenerListener to update the root node if the target of the file is changed because of a
SDK location change or a project target change | private final Runnable | mConditionalRecomputeRunnable | private final Runnable | mUiUpdateFromResourcesRunnable |
Constructors Summary |
---|
public GraphicalLayoutEditor(LayoutEditor layoutEditor)
mLayoutEditor = layoutEditor;
setEditDomain(new DefaultEditDomain(this));
setPartName("Layout");
IconFactory factory = IconFactory.getInstance();
mWarningImage = factory.getIcon("warning"); //$NON-NLS-1$
mMatchImage = factory.getIcon("match"); //$NON-NLS-1$
mErrorImage = factory.getIcon("error"); //$NON-NLS-1$
AdtPlugin.getDefault().addTargetListener(mTargetListener);
|
Methods Summary |
---|
void | activated()Responds to a page change that made the Graphical editor page the activated page.
if (mNeedsRecompute || mNeedsXmlReload) {
recomputeLayout();
}
| private com.android.layoutlib.api.ILayoutResult | computeLayout(com.android.ide.eclipse.adt.sdk.AndroidTargetData.LayoutBridge bridge, com.android.layoutlib.api.IXmlPullParser layoutDescription, java.lang.Object projectKey, int screenWidth, int screenHeight, int density, float xdpi, float ydpi, java.lang.String themeName, boolean isProjectTheme, java.util.Map projectResources, java.util.Map frameworkResources, com.android.layoutlib.api.IProjectCallback projectCallback, com.android.layoutlib.api.ILayoutLog logger)Computes a layout by calling the correct computeLayout method of ILayoutBridge based on
the implementation API level.
if (bridge.apiLevel >= 3) {
// newer api with boolean for separation of project/framework theme,
// and density support.
return bridge.bridge.computeLayout(layoutDescription,
projectKey, screenWidth, screenHeight, density, xdpi, ydpi,
themeName, isProjectTheme,
projectResources, frameworkResources, projectCallback,
logger);
} else if (bridge.apiLevel == 2) {
// api with boolean for separation of project/framework theme
return bridge.bridge.computeLayout(layoutDescription,
projectKey, screenWidth, screenHeight, themeName, isProjectTheme,
mConfiguredProjectRes, frameworkResources, mProjectCallback,
mLogger);
} else {
// oldest api with no density/dpi, and project theme boolean mixed
// into the theme name.
// change the string if it's a custom theme to make sure we can
// differentiate them
if (isProjectTheme) {
themeName = "*" + themeName; //$NON-NLS-1$
}
return bridge.bridge.computeLayout(layoutDescription,
projectKey, screenWidth, screenHeight, themeName,
mConfiguredProjectRes, frameworkResources, mProjectCallback,
mLogger);
}
| protected void | configureGraphicalViewer()
super.configureGraphicalViewer();
GraphicalViewer viewer = getGraphicalViewer();
viewer.setEditPartFactory(new UiElementsEditPartFactory(mParent.getDisplay()));
viewer.setRootEditPart(new ScalableFreeformRootEditPart());
// Disable the following -- we don't drag *from* the GraphicalViewer yet:
// viewer.addDragSourceListener(new TemplateTransferDragSourceListener(viewer));
viewer.addDropTargetListener(new DropListener(viewer));
| protected void | configurePaletteViewer()
super.configurePaletteViewer();
// Create a drag source listener on an edit part that is a viewer.
// What this does is use DND with a TemplateTransfer type which is actually
// the PaletteTemplateEntry held in the PaletteRoot.
TemplateTransferDragSourceListener dragSource =
new TemplateTransferDragSourceListener(getPaletteViewer());
// Create a drag source on the palette viewer.
// See the drag target associated with the GraphicalViewer in configureGraphicalViewer.
getPaletteViewer().addDragSourceListener(dragSource);
| private void | createAlternateLayout(com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration config)Creates a new layout file from the specificed {@link FolderConfiguration}.
new Job("Create Alternate Resource") {
@Override
protected IStatus run(IProgressMonitor monitor) {
// get the folder name
String folderName = config.getFolderName(ResourceFolderType.LAYOUT);
try {
// look to see if it exists.
// get the res folder
IFolder res = (IFolder)mEditedFile.getParent().getParent();
String path = res.getLocation().toOSString();
File newLayoutFolder = new File(path + File.separator + folderName);
if (newLayoutFolder.isFile()) {
// this should not happen since aapt would have complained
// before, but if one disable the automatic build, this could
// happen.
String message = String.format("File 'res/%1$s' is in the way!",
folderName);
AdtPlugin.displayError("Layout Creation", message);
return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, message);
} else if (newLayoutFolder.exists() == false) {
// create it.
newLayoutFolder.mkdir();
}
// now create the file
File newLayoutFile = new File(newLayoutFolder.getAbsolutePath() +
File.separator + mEditedFile.getName());
newLayoutFile.createNewFile();
InputStream input = mEditedFile.getContents();
FileOutputStream fos = new FileOutputStream(newLayoutFile);
byte[] data = new byte[512];
int count;
while ((count = input.read(data)) != -1) {
fos.write(data, 0, count);
}
input.close();
fos.close();
// refreshes the res folder to show up the new
// layout folder (if needed) and the file.
// We use a progress monitor to catch the end of the refresh
// to trigger the edit of the new file.
res.refreshLocal(IResource.DEPTH_INFINITE, new IProgressMonitor() {
public void done() {
mCurrentConfig.set(config);
mParent.getDisplay().asyncExec(new Runnable() {
public void run() {
onConfigurationChange();
}
});
}
public void beginTask(String name, int totalWork) {
// pass
}
public void internalWorked(double work) {
// pass
}
public boolean isCanceled() {
// pass
return false;
}
public void setCanceled(boolean value) {
// pass
}
public void setTaskName(String name) {
// pass
}
public void subTask(String name) {
// pass
}
public void worked(int work) {
// pass
}
});
} catch (IOException e2) {
String message = String.format(
"Failed to create File 'res/%1$s/%2$s' : %3$s",
folderName, mEditedFile.getName(), e2.getMessage());
AdtPlugin.displayError("Layout Creation", message);
return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
message, e2);
} catch (CoreException e2) {
String message = String.format(
"Failed to create File 'res/%1$s/%2$s' : %3$s",
folderName, mEditedFile.getName(), e2.getMessage());
AdtPlugin.displayError("Layout Creation", message);
return e2.getStatus();
}
return Status.OK_STATUS;
}
}.schedule();
| private org.eclipse.jface.action.MenuManager | createContextMenu(org.eclipse.gef.GraphicalViewer viewer)
MenuManager menuManager = new MenuManager();
menuManager.setRemoveAllWhenShown(true);
menuManager.addMenuListener(new ActionMenuListener(viewer));
return menuManager;
| private org.eclipse.swt.widgets.Label | createControlComposite(org.eclipse.swt.widgets.Composite parent, boolean grab)Creates a composite with no margin/spacing, and puts a {@link Label} in it with the matching
icon.
GridLayout gl;
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(gl = new GridLayout(2, false));
gl.marginHeight = gl.marginWidth = 0;
gl.horizontalSpacing = 0;
if (grab) {
composite.setLayoutData(
new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
}
// create the label
Label icon = new Label(composite, SWT.NONE);
icon.setImage(mMatchImage);
return icon;
| public void | createPartControl(org.eclipse.swt.widgets.Composite parent)
mParent = parent;
GridLayout gl;
GridData gd;
mClipboard = new Clipboard(parent.getDisplay());
parent.setLayout(gl = new GridLayout(1, false));
gl.marginHeight = gl.marginWidth = 0;
// create the top part for the configuration control
int cols = 10;
Composite topParent = new Composite(parent, SWT.NONE);
topParent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
topParent.setLayout(gl = new GridLayout(cols, false));
new Label(topParent, SWT.NONE).setText("MCC");
mCountryIcon = createControlComposite(topParent, true /* grab_horizontal */);
mCountry = new Text(mCountryIcon.getParent(), SWT.BORDER);
mCountry.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mCountry.addVerifyListener(new MobileCodeVerifier());
mCountry.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
onCountryCodeChange();
}
});
mCountry.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
onCountryCodeChange();
}
});
new Label(topParent, SWT.NONE).setText("MNC");
mNetworkIcon = createControlComposite(topParent, true /* grab_horizontal */);
mNetwork = new Text(mNetworkIcon.getParent(), SWT.BORDER);
mNetwork.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mNetwork.addVerifyListener(new MobileCodeVerifier());
mNetwork.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
onNetworkCodeChange();
}
});
mNetwork.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
onNetworkCodeChange();
}
});
new Label(topParent, SWT.NONE).setText("Lang");
mLanguageIcon = createControlComposite(topParent, true /* grab_horizontal */);
mLanguage = new Combo(mLanguageIcon.getParent(), SWT.DROP_DOWN);
mLanguage.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mLanguage.addVerifyListener(new LanguageRegionVerifier());
mLanguage.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
onLanguageChange();
}
public void widgetSelected(SelectionEvent e) {
onLanguageChange();
}
});
mLanguage.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
onLanguageChange();
}
});
new Label(topParent, SWT.NONE).setText("Region");
mRegionIcon = createControlComposite(topParent, true /* grab_horizontal */);
mRegion = new Combo(mRegionIcon.getParent(), SWT.DROP_DOWN);
mRegion.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mRegion.addVerifyListener(new LanguageRegionVerifier());
mRegion.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
onRegionChange();
}
public void widgetSelected(SelectionEvent e) {
onRegionChange();
}
});
mRegion.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
onRegionChange();
}
});
new Label(topParent, SWT.NONE).setText("Orient");
mOrientationIcon = createControlComposite(topParent, true /* grab_horizontal */);
mOrientation = new Combo(mOrientationIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY);
ScreenOrientation[] soValues = ScreenOrientation.values();
mOrientation.add("(Default)");
for (ScreenOrientation value : soValues) {
mOrientation.add(value.getDisplayValue());
}
mOrientation.select(0);
mOrientation.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mOrientation.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onOrientationChange();
}
});
new Label(topParent, SWT.NONE).setText("Density");
mDensityIcon = createControlComposite(topParent, true /* grab_horizontal */);
mDensity = new Text(mDensityIcon.getParent(), SWT.BORDER);
mDensity.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mDensity.addVerifyListener(new DensityVerifier());
mDensity.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
onDensityChange();
}
});
mDensity.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
onDensityChange();
}
});
new Label(topParent, SWT.NONE).setText("Touch");
mTouchIcon = createControlComposite(topParent, true /* grab_horizontal */);
mTouch = new Combo(mTouchIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY);
TouchScreenType[] tstValues = TouchScreenType.values();
mTouch.add("(Default)");
for (TouchScreenType value : tstValues) {
mTouch.add(value.getDisplayValue());
}
mTouch.select(0);
mTouch.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mTouch.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onTouchChange();
}
});
new Label(topParent, SWT.NONE).setText("Keybrd");
mKeyboardIcon = createControlComposite(topParent, true /* grab_horizontal */);
mKeyboard = new Combo(mKeyboardIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY);
KeyboardState[] ksValues = KeyboardState.values();
mKeyboard.add("(Default)");
for (KeyboardState value : ksValues) {
mKeyboard.add(value.getDisplayValue());
}
mKeyboard.select(0);
mKeyboard.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mKeyboard.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onKeyboardChange();
}
});
new Label(topParent, SWT.NONE).setText("Input");
mTextInputIcon = createControlComposite(topParent, true /* grab_horizontal */);
mTextInput = new Combo(mTextInputIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY);
TextInputMethod[] timValues = TextInputMethod.values();
mTextInput.add("(Default)");
for (TextInputMethod value : timValues) {
mTextInput.add(value.getDisplayValue());
}
mTextInput.select(0);
mTextInput.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mTextInput.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onTextInputChange();
}
});
new Label(topParent, SWT.NONE).setText("Nav");
mNavigationIcon = createControlComposite(topParent, true /* grab_horizontal */);
mNavigation = new Combo(mNavigationIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY);
NavigationMethod[] nValues = NavigationMethod.values();
mNavigation.add("(Default)");
for (NavigationMethod value : nValues) {
mNavigation.add(value.getDisplayValue());
}
mNavigation.select(0);
mNavigation.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mNavigation.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onNavigationChange();
}
});
Composite labelParent = new Composite(topParent, SWT.NONE);
labelParent.setLayout(gl = new GridLayout(8, false));
gl.marginWidth = gl.marginHeight = 0;
labelParent.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
gd.horizontalSpan = cols;
new Label(labelParent, SWT.NONE).setText("Editing config:");
mCurrentLayoutLabel = new Label(labelParent, SWT.NONE);
mCurrentLayoutLabel.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
gd.widthHint = 50;
new Label(labelParent, SWT.NONE).setText("Size");
mSizeIcon = createControlComposite(labelParent, false);
Composite sizeParent = new Composite(mSizeIcon.getParent(), SWT.NONE);
sizeParent.setLayout(gl = new GridLayout(3, false));
gl.marginWidth = gl.marginHeight = 0;
gl.horizontalSpacing = 0;
mSize1 = new Text(sizeParent, SWT.BORDER);
mSize1.setLayoutData(gd = new GridData());
gd.widthHint = 30;
new Label(sizeParent, SWT.NONE).setText("x");
mSize2 = new Text(sizeParent, SWT.BORDER);
mSize2.setLayoutData(gd = new GridData());
gd.widthHint = 30;
DimensionVerifier verifier = new DimensionVerifier();
mSize1.addVerifyListener(verifier);
mSize2.addVerifyListener(verifier);
SelectionListener sl = new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
onSizeChange();
}
public void widgetSelected(SelectionEvent e) {
onSizeChange();
}
};
mSize1.addSelectionListener(sl);
mSize2.addSelectionListener(sl);
ModifyListener sizeModifyListener = new ModifyListener() {
public void modifyText(ModifyEvent e) {
onSizeChange();
}
};
mSize1.addModifyListener(sizeModifyListener);
mSize2.addModifyListener(sizeModifyListener);
// first separator
Label separator = new Label(labelParent, SWT.SEPARATOR | SWT.VERTICAL);
separator.setLayoutData(gd = new GridData(
GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL));
gd.heightHint = 0;
mThemeCombo = new Combo(labelParent, SWT.READ_ONLY | SWT.DROP_DOWN);
mThemeCombo.setEnabled(false);
updateUIFromResources();
mThemeCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onThemeChange();
}
});
// second separator
separator = new Label(labelParent, SWT.SEPARATOR | SWT.VERTICAL);
separator.setLayoutData(gd = new GridData(
GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL));
gd.heightHint = 0;
mCreateButton = new Button(labelParent, SWT.PUSH | SWT.FLAT);
mCreateButton.setText("Create...");
mCreateButton.setEnabled(false);
mCreateButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
LayoutCreatorDialog dialog = new LayoutCreatorDialog(mCreateButton.getShell(),
mEditedFile.getName(), mCurrentConfig);
if (dialog.open() == Dialog.OK) {
final FolderConfiguration config = new FolderConfiguration();
dialog.getConfiguration(config);
createAlternateLayout(config);
}
}
});
// create a new composite that will contain the standard editor controls.
Composite editorParent = new Composite(parent, SWT.NONE);
editorParent.setLayoutData(new GridData(GridData.FILL_BOTH));
editorParent.setLayout(new FillLayout());
super.createPartControl(editorParent);
| void | deactivated()Responds to a page change that made the Graphical editor page the deactivated page
// nothing to be done here for now.
| void | displayConfigError()Displays an error icon in front of all the non-null qualifiers.
mCountryIcon.setImage(mMatchImage);
CountryCodeQualifier countryQualifier = mCurrentConfig.getCountryCodeQualifier();
if (countryQualifier != null) {
mCountryIcon.setImage(mErrorImage);
}
mNetworkIcon.setImage(mMatchImage);
NetworkCodeQualifier networkQualifier = mCurrentConfig.getNetworkCodeQualifier();
if (networkQualifier != null) {
mNetworkIcon.setImage(mErrorImage);
}
mLanguageIcon.setImage(mMatchImage);
LanguageQualifier languageQualifier = mCurrentConfig.getLanguageQualifier();
if (languageQualifier != null) {
mLanguageIcon.setImage(mErrorImage);
}
mRegionIcon.setImage(mMatchImage);
RegionQualifier regionQualifier = mCurrentConfig.getRegionQualifier();
if (regionQualifier != null) {
mRegionIcon.setImage(mErrorImage);
}
mOrientationIcon.setImage(mMatchImage);
ScreenOrientationQualifier orientationQualifier =
mCurrentConfig.getScreenOrientationQualifier();
if (orientationQualifier != null) {
mOrientationIcon.setImage(mErrorImage);
}
mDensityIcon.setImage(mMatchImage);
PixelDensityQualifier densityQualifier = mCurrentConfig.getPixelDensityQualifier();
if (densityQualifier != null) {
mDensityIcon.setImage(mErrorImage);
}
mTouchIcon.setImage(mMatchImage);
TouchScreenQualifier touchQualifier = mCurrentConfig.getTouchTypeQualifier();
if (touchQualifier != null) {
mTouchIcon.setImage(mErrorImage);
}
mKeyboardIcon.setImage(mMatchImage);
KeyboardStateQualifier keyboardQualifier = mCurrentConfig.getKeyboardStateQualifier();
if (keyboardQualifier != null) {
mKeyboardIcon.setImage(mErrorImage);
}
mTextInputIcon.setImage(mMatchImage);
TextInputMethodQualifier inputQualifier = mCurrentConfig.getTextInputMethodQualifier();
if (inputQualifier != null) {
mTextInputIcon.setImage(mErrorImage);
}
mNavigationIcon.setImage(mMatchImage);
NavigationMethodQualifier navigationQualifiter =
mCurrentConfig.getNavigationMethodQualifier();
if (navigationQualifiter != null) {
mNavigationIcon.setImage(mErrorImage);
}
mSizeIcon.setImage(mMatchImage);
ScreenDimensionQualifier sizeQualifier = mCurrentConfig.getScreenDimensionQualifier();
if (sizeQualifier != null) {
mSizeIcon.setImage(mErrorImage);
}
// update the string showing the folder name
String current = mCurrentConfig.toDisplayString();
mCurrentLayoutLabel.setText(current != null ? current : "(Default)");
| public void | dispose()
if (mTargetListener != null) {
AdtPlugin.getDefault().removeTargetListener(mTargetListener);
mTargetListener = null;
}
LayoutReloadMonitor.getMonitor().removeListener(mEditedFile.getProject(), this);
if (mClipboard != null) {
mClipboard.dispose();
mClipboard = null;
}
super.dispose();
| private void | doCreateMenuAction(org.eclipse.jface.action.IMenuManager manager, org.eclipse.gef.GraphicalViewer viewer, java.util.ArrayList selected)
if (selected != null) {
boolean hasXml = false;
for (UiElementNode uiNode : selected) {
if (uiNode.getXmlNode() != null) {
hasXml = true;
break;
}
}
if (hasXml) {
manager.add(new CopyCutAction(mLayoutEditor, getClipboard(),
null, selected, true /* cut */));
manager.add(new CopyCutAction(mLayoutEditor, getClipboard(),
null, selected, false /* cut */));
// Can't paste with more than one element selected (the selection is the target)
if (selected.size() <= 1) {
// Paste is not valid if it would add a second element on a terminal element
// which parent is a document -- an XML document can only have one child. This
// means paste is valid if the current UI node can have children or if the
// parent is not a document.
UiElementNode ui_root = selected.get(0).getUiRoot();
if (ui_root.getDescriptor().hasChildren() ||
!(ui_root.getUiParent() instanceof UiDocumentNode)) {
manager.add(new PasteAction(mLayoutEditor, getClipboard(),
selected.get(0)));
}
}
manager.add(new Separator());
}
}
// Append "add" and "remove" actions. They do the same thing as the add/remove
// buttons on the side.
IconFactory factory = IconFactory.getInstance();
final UiEditorActions uiActions = mLayoutEditor.getUiEditorActions();
// "Add" makes sense only if there's 0 or 1 item selected since the
// one selected item becomes the target.
if (selected == null || selected.size() <= 1) {
manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-2$
@Override
public void run() {
UiElementNode node = selected != null && selected.size() > 0 ? selected.get(0)
: null;
uiActions.doAdd(node, viewer.getControl().getShell());
}
});
}
if (selected != null) {
manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-2$
@Override
public void run() {
uiActions.doRemove(selected, viewer.getControl().getShell());
}
});
manager.add(new Separator());
manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-2$
@Override
public void run() {
uiActions.doUp(selected);
}
});
manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-2$
@Override
public void run() {
uiActions.doDown(selected);
}
});
}
| public void | doSave(org.eclipse.core.runtime.IProgressMonitor monitor)Save operation in the Graphical Layout Editor.
In our workflow, the model is owned by the Structured XML Editor.
The graphical layout editor just displays it -- thus we don't really
save anything here.
This must NOT call the parent editor part. At the contrary, the parent editor
part will call this *after* having done the actual save operation.
The only action this editor must do is mark the undo command stack as
being no longer dirty.
getCommandStack().markSaveLocation();
firePropertyChange(PROP_DIRTY);
| private void | doXmlReload(boolean force)Actually performs the XML reload
if (force || mNeedsXmlReload) {
GraphicalViewer viewer = getGraphicalViewer();
// try to preserve the selection before changing the content
SelectionManager selMan = viewer.getSelectionManager();
ISelection selection = selMan.getSelection();
try {
viewer.setContents(getModel());
} finally {
selMan.setSelection(selection);
}
mNeedsXmlReload = false;
}
| void | editNewFile(com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration configuration)Sets the UI for the edition of a new file.
// update the configuration UI
setConfiguration(configuration, true /*force*/);
// enable the create button if the current and edited config are not equals
mCreateButton.setEnabled(mEditedConfig.equals(mCurrentConfig) == false);
| public org.eclipse.draw2d.geometry.Rectangle | getBounds()
ScreenOrientation orientation = null;
if (mOrientation.getSelectionIndex() == 0) {
orientation = ScreenOrientation.PORTRAIT;
} else {
orientation = ScreenOrientation.getByIndex(
mOrientation.getSelectionIndex() - 1);
}
int s1, s2;
// get the size from the UI controls. If it fails, revert to default values.
try {
s1 = Integer.parseInt(mSize1.getText().trim());
} catch (NumberFormatException e) {
s1 = 480;
}
try {
s2 = Integer.parseInt(mSize2.getText().trim());
} catch (NumberFormatException e) {
s2 = 320;
}
// make sure s1 is bigger than s2
if (s1 < s2) {
int tmp = s1;
s1 = s2;
s2 = tmp;
}
switch (orientation) {
default:
case PORTRAIT:
return new Rectangle(0, 0, s2, s1);
case LANDSCAPE:
return new Rectangle(0, 0, s1, s2);
case SQUARE:
return new Rectangle(0, 0, s1, s1);
}
| public org.eclipse.swt.dnd.Clipboard | getClipboard()
return mClipboard;
| private java.util.Map | getConfiguredFrameworkResources()
if (mConfiguredFrameworkRes == null) {
ProjectResources frameworkRes = getFrameworkResources();
if (frameworkRes == null) {
AdtPlugin.log(IStatus.ERROR, "Failed to get ProjectResource for the framework");
}
// get the framework resource values based on the current config
mConfiguredFrameworkRes = frameworkRes.getConfiguredResources(mCurrentConfig);
}
return mConfiguredFrameworkRes;
| private com.android.ide.eclipse.editors.resources.manager.ProjectResources | getFrameworkResources()Returns a {@link ProjectResources} for the framework resources.
if (mEditedFile != null) {
Sdk currentSdk = Sdk.getCurrent();
if (currentSdk != null) {
IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject());
if (target != null) {
AndroidTargetData data = currentSdk.getTargetData(target);
if (data != null) {
return data.getFrameworkResources();
}
}
}
}
return null;
| public LayoutEditor | getLayoutEditor()
return mLayoutEditor;
| com.android.ide.eclipse.editors.uimodel.UiDocumentNode | getModel()
return mLayoutEditor.getUiRootNode();
| protected org.eclipse.gef.palette.PaletteRoot | getPaletteRoot()
mPaletteRoot = PaletteFactory.createPaletteRoot(mPaletteRoot,
mLayoutEditor.getTargetData());
return mPaletteRoot;
| protected void | initializeGraphicalViewer()
GraphicalViewer viewer = getGraphicalViewer();
viewer.setContents(getModel());
IEditorInput input = getEditorInput();
if (input instanceof FileEditorInput) {
FileEditorInput fileInput = (FileEditorInput)input;
mEditedFile = fileInput.getFile();
updateUIFromResources();
LayoutReloadMonitor.getMonitor().addListener(mEditedFile.getProject(), this);
} else {
// really this shouldn't happen! Log it in case it happens
mEditedFile = null;
AdtPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
input.toString());
}
| private boolean | isTheme(com.android.layoutlib.api.IResourceValue value, java.util.Map styleMap)Returns whether the given style is a theme.
This is done by making sure the parent is a theme.
if (value instanceof IStyleResourceValue) {
IStyleResourceValue style = (IStyleResourceValue)value;
boolean frameworkStyle = false;
String parentStyle = style.getParentStyle();
if (parentStyle == null) {
// if there is no specified parent style we look an implied one.
// For instance 'Theme.light' is implied child style of 'Theme',
// and 'Theme.light.fullscreen' is implied child style of 'Theme.light'
String name = style.getName();
int index = name.lastIndexOf('.");
if (index != -1) {
parentStyle = name.substring(0, index);
}
} else {
// remove the useless @ if it's there
if (parentStyle.startsWith("@")) {
parentStyle = parentStyle.substring(1);
}
// check for framework identifier.
if (parentStyle.startsWith("android:")) {
frameworkStyle = true;
parentStyle = parentStyle.substring("android:".length());
}
// at this point we could have the format style/<name>. we want only the name
if (parentStyle.startsWith("style/")) {
parentStyle = parentStyle.substring("style/".length());
}
}
if (frameworkStyle) {
// if the parent is a framework style, it has to be 'Theme' or 'Theme.*'
return parentStyle.equals("Theme") || parentStyle.startsWith("Theme.");
} else {
// if it's a project style, we check this is a theme.
value = styleMap.get(parentStyle);
if (value != null) {
return isTheme(value, styleMap);
}
}
}
return false;
| private void | onConfigurationChange()Looks for a file matching the new {@link FolderConfiguration} and attempts to open it.
If there is no match, notify the user.
mConfiguredFrameworkRes = mConfiguredProjectRes = null;
if (mEditedFile == null || mEditedConfig == null) {
return;
}
// get the resources of the file's project.
ProjectResources resources = ResourceManager.getInstance().getProjectResources(
mEditedFile.getProject());
// from the resources, look for a matching file
ResourceFile match = null;
if (resources != null) {
match = resources.getMatchingFile(mEditedFile.getName(),
ResourceFolderType.LAYOUT,
mCurrentConfig);
}
if (match != null) {
if (match.getFile().equals(mEditedFile) == false) {
try {
IDE.openEditor(
getSite().getWorkbenchWindow().getActivePage(),
match.getFile().getIFile());
// we're done!
return;
} catch (PartInitException e) {
// FIXME: do something!
}
}
// at this point, we have not opened a new file.
// update the configuration icons with the new edited config.
setConfiguration(mEditedConfig, false /*force*/);
// enable the create button if the current and edited config are not equals
mCreateButton.setEnabled(mEditedConfig.equals(mCurrentConfig) == false);
// Even though the layout doesn't change, the config changed, and referenced
// resources need to be updated.
recomputeLayout();
} else {
// update the configuration icons with the new edited config.
displayConfigError();
// enable the Create button
mCreateButton.setEnabled(true);
// display the error.
String message = String.format(
"No resources match the configuration\n \n\t%1$s\n \nChange the configuration or create:\n \n\tres/%2$s/%3$s\n \nYou can also click the 'Create' button above.",
mCurrentConfig.toDisplayString(),
mCurrentConfig.getFolderName(ResourceFolderType.LAYOUT),
mEditedFile.getName());
showErrorInEditor(message);
}
| private void | onCountryCodeChange()
// because mCountry triggers onCountryCodeChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
if (mDisableUpdates == true) {
return;
}
// update the current config
String value = mCountry.getText();
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setCountryCodeQualifier(null);
} else {
try {
CountryCodeQualifier qualifier = CountryCodeQualifier.getQualifier(
CountryCodeQualifier.getFolderSegment(Integer.parseInt(value)));
if (qualifier != null) {
mCurrentConfig.setCountryCodeQualifier(qualifier);
} else {
// Failure! Looks like the value is wrong (for instance a one letter string).
// We do nothing in this case.
mCountryIcon.setImage(mErrorImage);
return;
}
} catch (NumberFormatException e) {
// Looks like the code is not a number. This should not happen since the text
// field has a VerifyListener that prevents it.
mCurrentConfig.setCountryCodeQualifier(null);
mCountryIcon.setImage(mErrorImage);
}
}
// look for a file to open/create
onConfigurationChange();
| private void | onDensityChange()
// because mDensity triggers onDensityChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
if (mDisableUpdates == true) {
return;
}
// update the current config
String value = mDensity.getText();
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setPixelDensityQualifier(null);
} else {
try {
PixelDensityQualifier qualifier = PixelDensityQualifier.getQualifier(
PixelDensityQualifier.getFolderSegment(Integer.parseInt(value)));
if (qualifier != null) {
mCurrentConfig.setPixelDensityQualifier(qualifier);
} else {
// Failure! Looks like the value is wrong (for instance a one letter string).
// We do nothing in this case.
return;
}
} catch (NumberFormatException e) {
// Looks like the code is not a number. This should not happen since the text
// field has a VerifyListener that prevents it.
// We do nothing in this case.
mDensityIcon.setImage(mErrorImage);
return;
}
}
// look for a file to open/create
onConfigurationChange();
| private void | onKeyboardChange()
// update the current config
int index = mKeyboard.getSelectionIndex();
if (index != 0) {
mCurrentConfig.setKeyboardStateQualifier(new KeyboardStateQualifier(
KeyboardState.getByIndex(index-1)));
} else {
mCurrentConfig.setKeyboardStateQualifier(null);
}
// look for a file to open/create
onConfigurationChange();
| private void | onLanguageChange()Call back for language combo selection
// because mLanguage triggers onLanguageChange at each modification, the filling
// of the combo with data will trigger notifications, and we don't want that.
if (mDisableUpdates == true) {
return;
}
// update the current config
String value = mLanguage.getText();
updateRegionUi(null /* projectResources */, null /* frameworkResources */);
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setLanguageQualifier(null);
} else {
LanguageQualifier qualifier = null;
String segment = LanguageQualifier.getFolderSegment(value);
if (segment != null) {
qualifier = LanguageQualifier.getQualifier(segment);
}
if (qualifier != null) {
mCurrentConfig.setLanguageQualifier(qualifier);
} else {
// Failure! Looks like the value is wrong (for instance a one letter string).
mCurrentConfig.setLanguageQualifier(null);
mLanguageIcon.setImage(mErrorImage);
}
}
// look for a file to open/create
onConfigurationChange();
| private void | onNavigationChange()
// update the current config
int index = mNavigation.getSelectionIndex();
if (index != 0) {
mCurrentConfig.setNavigationMethodQualifier(new NavigationMethodQualifier(
NavigationMethod.getByIndex(index-1)));
} else {
mCurrentConfig.setNavigationMethodQualifier(null);
}
// look for a file to open/create
onConfigurationChange();
| private void | onNetworkCodeChange()
// because mNetwork triggers onNetworkCodeChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
if (mDisableUpdates == true) {
return;
}
// update the current config
String value = mNetwork.getText();
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setNetworkCodeQualifier(null);
} else {
try {
NetworkCodeQualifier qualifier = NetworkCodeQualifier.getQualifier(
NetworkCodeQualifier.getFolderSegment(Integer.parseInt(value)));
if (qualifier != null) {
mCurrentConfig.setNetworkCodeQualifier(qualifier);
} else {
// Failure! Looks like the value is wrong (for instance a one letter string).
// We do nothing in this case.
mNetworkIcon.setImage(mErrorImage);
return;
}
} catch (NumberFormatException e) {
// Looks like the code is not a number. This should not happen since the text
// field has a VerifyListener that prevents it.
mCurrentConfig.setNetworkCodeQualifier(null);
mNetworkIcon.setImage(mErrorImage);
}
}
// look for a file to open/create
onConfigurationChange();
| private void | onOrientationChange()
// update the current config
int index = mOrientation.getSelectionIndex();
if (index != 0) {
mCurrentConfig.setScreenOrientationQualifier(new ScreenOrientationQualifier(
ScreenOrientation.getByIndex(index-1)));
} else {
mCurrentConfig.setScreenOrientationQualifier(null);
}
// look for a file to open/create
onConfigurationChange();
| private void | onRegionChange()
// because mRegion triggers onRegionChange at each modification, the filling
// of the combo with data will trigger notifications, and we don't want that.
if (mDisableUpdates == true) {
return;
}
// update the current config
String value = mRegion.getText();
// empty string, means no qualifier.
if (value.length() == 0) {
mCurrentConfig.setRegionQualifier(null);
} else {
RegionQualifier qualifier = null;
String segment = RegionQualifier.getFolderSegment(value);
if (segment != null) {
qualifier = RegionQualifier.getQualifier(segment);
}
if (qualifier != null) {
mCurrentConfig.setRegionQualifier(qualifier);
} else {
// Failure! Looks like the value is wrong (for instance a one letter string).
mCurrentConfig.setRegionQualifier(null);
mRegionIcon.setImage(mErrorImage);
}
}
// look for a file to open/create
onConfigurationChange();
| private void | onSizeChange()
// because mSize1 and mSize2 trigger onSizeChange at each modification, calling setText()
// will trigger notifications, and we don't want that.
if (mDisableUpdates == true) {
return;
}
// update the current config
String size1 = mSize1.getText();
String size2 = mSize2.getText();
// if only one of the strings is empty, do nothing
if ((size1.length() == 0) ^ (size2.length() == 0)) {
mSizeIcon.setImage(mErrorImage);
return;
} else if (size1.length() == 0 && size2.length() == 0) {
// both sizes are empty: remove the qualifier.
mCurrentConfig.setScreenDimensionQualifier(null);
} else {
ScreenDimensionQualifier qualifier = ScreenDimensionQualifier.getQualifier(size1,
size2);
if (qualifier != null) {
mCurrentConfig.setScreenDimensionQualifier(qualifier);
} else {
// Failure! Looks like the value is wrong.
// we do nothing in this case.
return;
}
}
// look for a file to open/create
onConfigurationChange();
| private void | onTextInputChange()
// update the current config
int index = mTextInput.getSelectionIndex();
if (index != 0) {
mCurrentConfig.setTextInputMethodQualifier(new TextInputMethodQualifier(
TextInputMethod.getByIndex(index-1)));
} else {
mCurrentConfig.setTextInputMethodQualifier(null);
}
// look for a file to open/create
onConfigurationChange();
| private void | onThemeChange()
int themeIndex = mThemeCombo.getSelectionIndex();
if (themeIndex != -1) {
String theme = mThemeCombo.getItem(themeIndex);
if (theme.equals(THEME_SEPARATOR)) {
mThemeCombo.select(0);
}
recomputeLayout();
}
| private void | onTouchChange()
// update the current config
int index = mTouch.getSelectionIndex();
if (index != 0) {
mCurrentConfig.setTouchTypeQualifier(new TouchScreenQualifier(
TouchScreenType.getByIndex(index-1)));
} else {
mCurrentConfig.setTouchTypeQualifier(null);
}
// look for a file to open/create
onConfigurationChange();
| void | onXmlModelChanged()Callback for XML model changed. Only update/recompute the layout if the editor is visible
if (mLayoutEditor.isGraphicalEditorActive()) {
doXmlReload(true /* force */);
recomputeLayout();
} else {
mNeedsXmlReload = true;
}
| void | recomputeLayout()Recomputes the layout with the help of layoutlib.
doXmlReload(false /* force */);
try {
// check that the resource exists. If the file is opened but the project is closed
// or deleted for some reason (changed from outside of eclipse), then this will
// return false;
if (mEditedFile.exists() == false) {
String message = String.format("Resource '%1$s' does not exist.",
mEditedFile.getFullPath().toString());
showErrorInEditor(message);
return;
}
IProject iProject = mEditedFile.getProject();
if (mEditedFile.isSynchronized(IResource.DEPTH_ZERO) == false) {
String message = String.format("%1$s is out of sync. Please refresh.",
mEditedFile.getName());
showErrorInEditor(message);
// also print it in the error console.
AdtPlugin.printErrorToConsole(iProject.getName(), message);
return;
}
Sdk currentSdk = Sdk.getCurrent();
if (currentSdk != null) {
IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject());
if (target == null) {
showErrorInEditor("The project target is not set.");
return;
}
AndroidTargetData data = currentSdk.getTargetData(target);
if (data == null) {
// It can happen that the workspace refreshes while the SDK is loading its
// data, which could trigger a redraw of the opened layout if some resources
// changed while Eclipse is closed.
// In this case data could be null, but this is not an error.
// We can just silently return, as all the opened editors are automatically
// refreshed once the SDK finishes loading.
if (AdtPlugin.getDefault().getSdkLoadStatus() != LoadStatus.LOADING) {
showErrorInEditor(String.format(
"The project target (%s) was not properly loaded.",
target.getName()));
}
return;
}
// check there is actually a model (maybe the file is empty).
UiDocumentNode model = getModel();
if (model.getUiChildren().size() == 0) {
showErrorInEditor("No Xml content. Go to the Outline view and add nodes.");
return;
}
LayoutBridge bridge = data.getLayoutBridge();
if (bridge.bridge != null) { // bridge can never be null.
ResourceManager resManager = ResourceManager.getInstance();
ProjectResources projectRes = resManager.getProjectResources(iProject);
if (projectRes == null) {
return;
}
// get the resources of the file's project.
if (mConfiguredProjectRes == null) {
// make sure they are loaded
projectRes.loadAll();
// get the project resource values based on the current config
mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
}
// get the framework resources
Map<String, Map<String, IResourceValue>> frameworkResources =
getConfiguredFrameworkResources();
if (mConfiguredProjectRes != null && frameworkResources != null) {
if (mProjectCallback == null) {
mProjectCallback = new ProjectCallback(
bridge.classLoader, projectRes, iProject);
}
if (mLogger == null) {
mLogger = new ILayoutLog() {
public void error(String message) {
AdtPlugin.printErrorToConsole(mEditedFile.getName(), message);
}
public void error(Throwable error) {
String message = error.getMessage();
if (message == null) {
message = error.getClass().getName();
}
PrintStream ps = new PrintStream(AdtPlugin.getErrorStream());
error.printStackTrace(ps);
}
public void warning(String message) {
AdtPlugin.printToConsole(mEditedFile.getName(), message);
}
};
}
// get the selected theme
int themeIndex = mThemeCombo.getSelectionIndex();
if (themeIndex != -1) {
String theme = mThemeCombo.getItem(themeIndex);
// Compute the layout
UiElementPullParser parser = new UiElementPullParser(getModel());
Rectangle rect = getBounds();
boolean isProjectTheme = themeIndex >= mPlatformThemeCount;
// FIXME pass the density/dpi from somewhere (resource config or skin).
ILayoutResult result = computeLayout(bridge, parser,
iProject /* projectKey */,
rect.width, rect.height, 160, 160.f, 160.f,
theme, isProjectTheme,
mConfiguredProjectRes, frameworkResources, mProjectCallback,
mLogger);
// update the UiElementNode with the layout info.
if (result.getSuccess() == ILayoutResult.SUCCESS) {
model.setEditData(result.getImage());
updateNodeWithBounds(result.getRootView());
} else {
String message = result.getErrorMessage();
// Reset the edit data for all the nodes.
resetNodeBounds(model);
if (message != null) {
// set the error in the top element.
model.setEditData(message);
}
}
model.refreshUi();
}
}
} else {
// SDK is loaded but not the layout library!
String message = null;
// check whether the bridge managed to load, or not
if (bridge.status == LoadStatus.LOADING) {
message = String.format(
"Eclipse is loading framework information and the Layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.",
mEditedFile.getName());
} else {
message = String.format("Eclipse failed to load the framework information and the Layout library!");
}
showErrorInEditor(message);
}
} else {
String message = String.format(
"Eclipse is loading the SDK.\n%1$s will refresh automatically once the process is finished.",
mEditedFile.getName());
showErrorInEditor(message);
}
} finally {
// no matter the result, we are done doing the recompute based on the latest
// resource/code change.
mNeedsRecompute = false;
}
| void | reloadEditor()Reloads this editor, by getting the new model from the {@link LayoutEditor}.
GraphicalViewer viewer = getGraphicalViewer();
viewer.setContents(getModel());
IEditorInput input = mLayoutEditor.getEditorInput();
setInput(input);
if (input instanceof FileEditorInput) {
FileEditorInput fileInput = (FileEditorInput)input;
mEditedFile = fileInput.getFile();
} else {
// really this shouldn't happen! Log it in case it happens
mEditedFile = null;
AdtPlugin.log(IStatus.ERROR, "Input is not of type FileEditorInput: %1$s",
input.toString());
}
| public void | reloadLayout(boolean codeChange, boolean rChange, boolean resChange)
boolean recompute = rChange;
if (resChange) {
recompute = true;
// TODO: differentiate between single and multi resource file changed, and whether the resource change affects the cache.
// force a reparse in case a value XML file changed.
mConfiguredProjectRes = null;
// clear the cache in the bridge in case a bitmap/9-patch changed.
IAndroidTarget target = Sdk.getCurrent().getTarget(mEditedFile.getProject());
if (target != null) {
AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
if (data != null) {
LayoutBridge bridge = data.getLayoutBridge();
if (bridge.bridge != null) {
bridge.bridge.clearCaches(mEditedFile.getProject());
}
}
}
mParent.getDisplay().asyncExec(mUiUpdateFromResourcesRunnable);
}
if (codeChange) {
// only recompute if the custom view loader was used to load some code.
if (mProjectCallback != null && mProjectCallback.isUsed()) {
mProjectCallback = null;
recompute = true;
}
}
if (recompute) {
mParent.getDisplay().asyncExec(mConditionalRecomputeRunnable);
}
| void | reloadPalette()
PaletteFactory.createPaletteRoot(mPaletteRoot, mLayoutEditor.getTargetData());
| public org.eclipse.swt.graphics.ImageData | renderWidget(com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor descriptor)Renders an Android View described by a {@link ViewElementDescriptor}.
This uses the wrap_content mode for both layout_width and
layout_height , and use the class name for the text attribute.
if (mEditedFile == null) {
return null;
}
IAndroidTarget target = Sdk.getCurrent().getTarget(mEditedFile.getProject());
if (target == null) {
return null;
}
AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
if (data == null) {
return null;
}
LayoutBridge bridge = data.getLayoutBridge();
if (bridge.bridge != null) { // bridge can never be null.
ResourceManager resManager = ResourceManager.getInstance();
ProjectCallback projectCallback = null;
Map<String, Map<String, IResourceValue>> configuredProjectResources = null;
if (mEditedFile != null) {
ProjectResources projectRes = resManager.getProjectResources(
mEditedFile.getProject());
projectCallback = new ProjectCallback(bridge.classLoader,
projectRes, mEditedFile.getProject());
// get the configured resources for the project
// get the resources of the file's project.
if (mConfiguredProjectRes == null && projectRes != null) {
// make sure they are loaded
projectRes.loadAll();
// get the project resource values based on the current config
mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig);
}
configuredProjectResources = mConfiguredProjectRes;
} else {
// we absolutely need a Map of configured project resources.
configuredProjectResources = new HashMap<String, Map<String, IResourceValue>>();
}
// get the framework resources
Map<String, Map<String, IResourceValue>> frameworkResources =
getConfiguredFrameworkResources();
if (configuredProjectResources != null && frameworkResources != null) {
// get the selected theme
int themeIndex = mThemeCombo.getSelectionIndex();
if (themeIndex != -1) {
String theme = mThemeCombo.getItem(themeIndex);
// Render a single object as described by the ViewElementDescriptor.
WidgetPullParser parser = new WidgetPullParser(descriptor);
ILayoutResult result = computeLayout(bridge, parser,
null /* projectKey */,
300 /* width */, 300 /* height */, 160 /*density*/,
160.f /*xdpi*/, 160.f /*ydpi*/, theme,
themeIndex >= mPlatformThemeCount /*isProjectTheme*/,
configuredProjectResources, frameworkResources, projectCallback,
null /* logger */);
// update the UiElementNode with the layout info.
if (result.getSuccess() == ILayoutResult.SUCCESS) {
BufferedImage largeImage = result.getImage();
// we need to resize it to the actual widget size, and convert it into
// an SWT image object.
int width = result.getRootView().getRight();
int height = result.getRootView().getBottom();
Raster raster = largeImage.getData(new java.awt.Rectangle(width, height));
int[] imageDataBuffer = ((DataBufferInt)raster.getDataBuffer()).getData();
ImageData imageData = new ImageData(width, height, 32,
new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF));
imageData.setPixels(0, 0, imageDataBuffer.length, imageDataBuffer, 0);
return imageData;
}
}
}
}
return null;
| private void | resetNodeBounds(com.android.ide.eclipse.editors.uimodel.UiElementNode node)
node.setEditData(null);
List<UiElementNode> children = node.getUiChildren();
for (UiElementNode child : children) {
resetNodeBounds(child);
}
| void | selectModel(com.android.ide.eclipse.editors.uimodel.UiElementNode uiNodeModel)Used by LayoutEditor.UiEditorActions.selectUiNode to select a new UI Node
created by {@link ElementCreateCommand#execute()}.
GraphicalViewer viewer = getGraphicalViewer();
// Give focus to the graphical viewer (in case the outline has it)
viewer.getControl().forceFocus();
Object editPart = viewer.getEditPartRegistry().get(uiNodeModel);
if (editPart instanceof EditPart) {
viewer.select((EditPart)editPart);
}
| void | setConfiguration(com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration config, boolean force)Update the UI controls state with a given {@link FolderConfiguration}.
If force is set to true the UI will be changed to exactly reflect
config, otherwise, if a qualifier is not present in config,
the UI control is not modified. However if the value in the control is not the default value,
a warning icon is shown.
mDisableUpdates = true; // we do not want to trigger onXXXChange when setting new values in the widgets.
mEditedConfig = config;
mConfiguredFrameworkRes = mConfiguredProjectRes = null;
mCountryIcon.setImage(mMatchImage);
CountryCodeQualifier countryQualifier = config.getCountryCodeQualifier();
if (countryQualifier != null) {
mCountry.setText(String.format("%1$d", countryQualifier.getCode()));
mCurrentConfig.setCountryCodeQualifier(countryQualifier);
} else if (force) {
mCountry.setText(""); //$NON-NLS-1$
mCurrentConfig.setCountryCodeQualifier(null);
} else if (mCountry.getText().length() > 0) {
mCountryIcon.setImage(mWarningImage);
}
mNetworkIcon.setImage(mMatchImage);
NetworkCodeQualifier networkQualifier = config.getNetworkCodeQualifier();
if (networkQualifier != null) {
mNetwork.setText(String.format("%1$d", networkQualifier.getCode()));
mCurrentConfig.setNetworkCodeQualifier(networkQualifier);
} else if (force) {
mNetwork.setText(""); //$NON-NLS-1$
mCurrentConfig.setNetworkCodeQualifier(null);
} else if (mNetwork.getText().length() > 0) {
mNetworkIcon.setImage(mWarningImage);
}
mLanguageIcon.setImage(mMatchImage);
LanguageQualifier languageQualifier = config.getLanguageQualifier();
if (languageQualifier != null) {
mLanguage.setText(languageQualifier.getValue());
mCurrentConfig.setLanguageQualifier(languageQualifier);
} else if (force) {
mLanguage.setText(""); //$NON-NLS-1$
mCurrentConfig.setLanguageQualifier(null);
} else if (mLanguage.getText().length() > 0) {
mLanguageIcon.setImage(mWarningImage);
}
mRegionIcon.setImage(mMatchImage);
RegionQualifier regionQualifier = config.getRegionQualifier();
if (regionQualifier != null) {
mRegion.setText(regionQualifier.getValue());
mCurrentConfig.setRegionQualifier(regionQualifier);
} else if (force) {
mRegion.setText(""); //$NON-NLS-1$
mCurrentConfig.setRegionQualifier(null);
} else if (mRegion.getText().length() > 0) {
mRegionIcon.setImage(mWarningImage);
}
mOrientationIcon.setImage(mMatchImage);
ScreenOrientationQualifier orientationQualifier = config.getScreenOrientationQualifier();
if (orientationQualifier != null) {
mOrientation.select(
ScreenOrientation.getIndex(orientationQualifier.getValue()) + 1);
mCurrentConfig.setScreenOrientationQualifier(orientationQualifier);
} else if (force) {
mOrientation.select(0);
mCurrentConfig.setScreenOrientationQualifier(null);
} else if (mOrientation.getSelectionIndex() != 0) {
mOrientationIcon.setImage(mWarningImage);
}
mDensityIcon.setImage(mMatchImage);
PixelDensityQualifier densityQualifier = config.getPixelDensityQualifier();
if (densityQualifier != null) {
mDensity.setText(String.format("%1$d", densityQualifier.getValue()));
mCurrentConfig.setPixelDensityQualifier(densityQualifier);
} else if (force) {
mDensity.setText(""); //$NON-NLS-1$
mCurrentConfig.setPixelDensityQualifier(null);
} else if (mDensity.getText().length() > 0) {
mDensityIcon.setImage(mWarningImage);
}
mTouchIcon.setImage(mMatchImage);
TouchScreenQualifier touchQualifier = config.getTouchTypeQualifier();
if (touchQualifier != null) {
mTouch.select(TouchScreenType.getIndex(touchQualifier.getValue()) + 1);
mCurrentConfig.setTouchTypeQualifier(touchQualifier);
} else if (force) {
mTouch.select(0);
mCurrentConfig.setTouchTypeQualifier(null);
} else if (mTouch.getSelectionIndex() != 0) {
mTouchIcon.setImage(mWarningImage);
}
mKeyboardIcon.setImage(mMatchImage);
KeyboardStateQualifier keyboardQualifier = config.getKeyboardStateQualifier();
if (keyboardQualifier != null) {
mKeyboard.select(KeyboardState.getIndex(keyboardQualifier.getValue()) + 1);
mCurrentConfig.setKeyboardStateQualifier(keyboardQualifier);
} else if (force) {
mKeyboard.select(0);
mCurrentConfig.setKeyboardStateQualifier(null);
} else if (mKeyboard.getSelectionIndex() != 0) {
mKeyboardIcon.setImage(mWarningImage);
}
mTextInputIcon.setImage(mMatchImage);
TextInputMethodQualifier inputQualifier = config.getTextInputMethodQualifier();
if (inputQualifier != null) {
mTextInput.select(TextInputMethod.getIndex(inputQualifier.getValue()) + 1);
mCurrentConfig.setTextInputMethodQualifier(inputQualifier);
} else if (force) {
mTextInput.select(0);
mCurrentConfig.setTextInputMethodQualifier(null);
} else if (mTextInput.getSelectionIndex() != 0) {
mTextInputIcon.setImage(mWarningImage);
}
mNavigationIcon.setImage(mMatchImage);
NavigationMethodQualifier navigationQualifiter = config.getNavigationMethodQualifier();
if (navigationQualifiter != null) {
mNavigation.select(
NavigationMethod.getIndex(navigationQualifiter.getValue()) + 1);
mCurrentConfig.setNavigationMethodQualifier(navigationQualifiter);
} else if (force) {
mNavigation.select(0);
mCurrentConfig.setNavigationMethodQualifier(null);
} else if (mNavigation.getSelectionIndex() != 0) {
mNavigationIcon.setImage(mWarningImage);
}
mSizeIcon.setImage(mMatchImage);
ScreenDimensionQualifier sizeQualifier = config.getScreenDimensionQualifier();
if (sizeQualifier != null) {
mSize1.setText(String.format("%1$d", sizeQualifier.getValue1()));
mSize2.setText(String.format("%1$d", sizeQualifier.getValue2()));
mCurrentConfig.setScreenDimensionQualifier(sizeQualifier);
} else if (force) {
mSize1.setText(""); //$NON-NLS-1$
mSize2.setText(""); //$NON-NLS-1$
mCurrentConfig.setScreenDimensionQualifier(null);
} else if (mSize1.getText().length() > 0 && mSize2.getText().length() > 0) {
mSizeIcon.setImage(mWarningImage);
}
// update the string showing the folder name
String current = config.toDisplayString();
mCurrentLayoutLabel.setText(current != null ? current : "(Default)");
mDisableUpdates = false;
| protected void | setGraphicalViewer(org.eclipse.gef.GraphicalViewer viewer)
super.setGraphicalViewer(viewer);
// TODO: viewer.setKeyHandler()
viewer.setContextMenu(createContextMenu(viewer));
| private void | showErrorInEditor(java.lang.String message)
// get the model to display the error directly in the editor
UiDocumentNode model = getModel();
// Reset the edit data for all the nodes.
resetNodeBounds(model);
if (message != null) {
// set the error in the top element.
model.setEditData(message);
}
model.refreshUi();
| private void | updateNodeWithBounds(com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo r)
if (r != null) {
// update the node itself, as the viewKey is the XML node in this implementation.
Object viewKey = r.getViewKey();
if (viewKey instanceof UiElementNode) {
Rectangle bounds = new Rectangle(r.getLeft(), r.getTop(),
r.getRight()-r.getLeft(), r.getBottom() - r.getTop());
((UiElementNode)viewKey).setEditData(bounds);
}
// and then its children.
ILayoutViewInfo[] children = r.getChildren();
if (children != null) {
for (ILayoutViewInfo child : children) {
updateNodeWithBounds(child);
}
}
}
| private void | updateRegionUi(com.android.ide.eclipse.editors.resources.manager.ProjectResources projectResources, com.android.ide.eclipse.editors.resources.manager.ProjectResources frameworkResources)Update the Region UI widget based on the current language selection
if (projectResources == null && mEditedFile != null) {
projectResources = ResourceManager.getInstance().getProjectResources(
mEditedFile.getProject());
}
if (frameworkResources == null) {
frameworkResources = getFrameworkResources();
}
String currentLanguage = mLanguage.getText();
Set<String> set = null;
if (projectResources != null) {
set = projectResources.getRegions(currentLanguage);
}
if (frameworkResources != null) {
if (set != null) {
Set<String> set2 = frameworkResources.getRegions(currentLanguage);
set.addAll(set2);
} else {
set = frameworkResources.getRegions(currentLanguage);
}
}
if (set != null) {
mDisableUpdates = true;
mRegion.removeAll();
for (String region : set) {
mRegion.add(region);
}
mDisableUpdates = false;
}
| private void | updateUIFromResources()Updates the UI from values in the resources, such as languages, regions, themes, etc...
This must be called from the UI thread.
ResourceManager manager = ResourceManager.getInstance();
ProjectResources frameworkProject = getFrameworkResources();
mDisableUpdates = true;
// Reset stuff
int selection = mThemeCombo.getSelectionIndex();
mThemeCombo.removeAll();
mPlatformThemeCount = 0;
mLanguage.removeAll();
Set<String> languages = new HashSet<String>();
ArrayList<String> themes = new ArrayList<String>();
// get the themes, and languages from the Framework.
if (frameworkProject != null) {
// get the configured resources for the framework
Map<String, Map<String, IResourceValue>> frameworResources =
getConfiguredFrameworkResources();
if (frameworResources != null) {
// get the styles.
Map<String, IResourceValue> styles = frameworResources.get(
ResourceType.STYLE.getName());
// collect the themes out of all the styles.
for (IResourceValue value : styles.values()) {
String name = value.getName();
if (name.startsWith("Theme.") || name.equals("Theme")) {
themes.add(value.getName());
mPlatformThemeCount++;
}
}
// sort them and add them to the combo
Collections.sort(themes);
for (String theme : themes) {
mThemeCombo.add(theme);
}
mPlatformThemeCount = themes.size();
themes.clear();
}
// now get the languages from the framework.
Set<String> frameworkLanguages = frameworkProject.getLanguages();
if (frameworkLanguages != null) {
languages.addAll(frameworkLanguages);
}
}
// now get the themes and languages from the project.
ProjectResources project = null;
if (mEditedFile != null) {
project = manager.getProjectResources(mEditedFile.getProject());
// in cases where the opened file is not linked to a project, this could be null.
if (project != null) {
// get the configured resources for the project
if (mConfiguredProjectRes == null) {
// make sure they are loaded
project.loadAll();
// get the project resource values based on the current config
mConfiguredProjectRes = project.getConfiguredResources(mCurrentConfig);
}
if (mConfiguredProjectRes != null) {
// get the styles.
Map<String, IResourceValue> styleMap = mConfiguredProjectRes.get(
ResourceType.STYLE.getName());
if (styleMap != null) {
// collect the themes out of all the styles, ie styles that extend,
// directly or indirectly a platform theme.
for (IResourceValue value : styleMap.values()) {
if (isTheme(value, styleMap)) {
themes.add(value.getName());
}
}
// sort them and add them the to the combo.
if (mPlatformThemeCount > 0 && themes.size() > 0) {
mThemeCombo.add(THEME_SEPARATOR);
}
Collections.sort(themes);
for (String theme : themes) {
mThemeCombo.add(theme);
}
}
}
// now get the languages from the project.
Set<String> projectLanguages = project.getLanguages();
if (projectLanguages != null) {
languages.addAll(projectLanguages);
}
}
}
// add the languages to the Combo
for (String language : languages) {
mLanguage.add(language);
}
mDisableUpdates = false;
// and update the Region UI based on the current language
updateRegionUi(project, frameworkProject);
// handle default selection of themes
if (mThemeCombo.getItemCount() > 0) {
mThemeCombo.setEnabled(true);
if (selection == -1) {
selection = 0;
}
if (mThemeCombo.getItemCount() <= selection) {
mThemeCombo.select(0);
} else {
mThemeCombo.select(selection);
}
} else {
mThemeCombo.setEnabled(false);
}
|
|