use of com.android.tools.idea.rendering.RenderResult in project android by JetBrains.
the class NlPreviewManager method processFileEditorChange.
private void processFileEditorChange(@Nullable final TextEditor newEditor) {
if (myPendingShowComponent != null) {
myPendingShowComponent.removeHierarchyListener(myHierarchyListener);
myPendingShowComponent = null;
}
myToolWindowUpdateQueue.cancelAllUpdates();
myToolWindowUpdateQueue.queue(new Update("update") {
@Override
public void run() {
if (!myToolWindowReady || myToolWindowDisposed) {
return;
}
boolean renderImmediately = myRenderImmediately;
myRenderImmediately = false;
final Editor activeEditor = newEditor != null ? newEditor.getEditor() : null;
if (myToolWindow == null) {
if (activeEditor == null) {
return;
} else if (!activeEditor.getComponent().isShowing()) {
// per project frame.)
if (!mySeenEditor) {
myPendingShowComponent = activeEditor.getComponent();
if (myHierarchyListener == null) {
myHierarchyListener = new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent hierarchyEvent) {
if ((hierarchyEvent.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
if (hierarchyEvent.getComponent() == myPendingShowComponent && myPendingShowComponent.isShowing()) {
myPendingShowComponent.removeHierarchyListener(myHierarchyListener);
mySeenEditor = true;
myPendingShowComponent = null;
processFileEditorChange(getActiveLayoutXmlEditor());
}
}
}
};
}
myPendingShowComponent.addHierarchyListener(myHierarchyListener);
}
return;
}
mySeenEditor = true;
initToolWindow();
}
final AndroidEditorSettings settings = AndroidEditorSettings.getInstance();
final boolean hideForNonLayoutFiles = settings.getGlobalState().isHideForNonLayoutFiles();
if (activeEditor == null) {
myToolWindowForm.setFile(null);
myToolWindow.setAvailable(!hideForNonLayoutFiles, null);
return;
}
final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(activeEditor.getDocument());
myToolWindowForm.setFile(psiFile);
if (psiFile == null) {
myToolWindow.setAvailable(!hideForNonLayoutFiles, null);
return;
}
myToolWindow.setAvailable(true, null);
final boolean visible = AndroidEditorSettings.getInstance().getGlobalState().isVisible();
if (visible) {
// tool window is shown and the time the render has completed
if (!myToolWindow.isVisible()) {
RenderResult renderResult = myToolWindowForm.getRenderResult();
if (renderResult != null && renderResult.getFile() != psiFile) {
myToolWindowForm.setRenderResult(RenderResult.createBlank(psiFile));
}
}
myToolWindow.show(null);
}
}
});
}
use of com.android.tools.idea.rendering.RenderResult in project android by JetBrains.
the class NlUsageTrackerManager method logRenderResult.
@Override
public void logRenderResult(@Nullable NlModel.ChangeType trigger, @NotNull RenderResult result, long totalRenderTimeMs) {
// Renders are a quite common event so we sample them
if (!shouldLog(LOG_RENDER_PERCENT)) {
return;
}
logStudioEvent(LayoutEditorEvent.LayoutEditorEventType.RENDER, (event) -> {
LayoutEditorRenderResult.Builder builder = LayoutEditorRenderResult.newBuilder().setResultCode(result.getRenderResult().getStatus().ordinal()).setTotalRenderTimeMs(totalRenderTimeMs);
if (trigger != null) {
switch(trigger) {
case RESOURCE_EDIT:
case RESOURCE_CHANGED:
builder.setTrigger(LayoutEditorRenderResult.Trigger.RESOURCE_CHANGE);
break;
case EDIT:
case ADD_COMPONENTS:
case DELETE:
case DND_COMMIT:
case DND_END:
case DROP:
case RESIZE_END:
case RESIZE_COMMIT:
builder.setTrigger(LayoutEditorRenderResult.Trigger.EDIT);
break;
case REQUEST_RENDER:
builder.setTrigger(LayoutEditorRenderResult.Trigger.USER);
break;
case BUILD:
builder.setTrigger(LayoutEditorRenderResult.Trigger.BUILD);
break;
case CONFIGURATION_CHANGE:
case UPDATE_HIERARCHY:
break;
}
}
builder.setComponentCount((int) result.getRootViews().stream().flatMap(s -> Stream.concat(s.getChildren().stream(), Stream.of(s))).count());
RenderErrorModel errorModel = RenderErrorModelFactory.createErrorModel(result, null);
builder.setTotalIssueCount(errorModel.getSize());
if (errorModel.getSize() > 0) {
int errorCount = 0;
int fidelityWarningCount = 0;
for (RenderErrorModel.Issue issue : errorModel.getIssues()) {
if (HighlightSeverity.ERROR.equals(issue.getSeverity())) {
errorCount++;
} else if (issue.getSummary().startsWith("Layout fid")) {
fidelityWarningCount++;
}
}
builder.setErrorCount(errorCount).setFidelityWarningCount(fidelityWarningCount);
}
event.setRenderResult(builder.build());
});
}
use of com.android.tools.idea.rendering.RenderResult in project android by JetBrains.
the class GradleRenderErrorContributorTest method setUp.
@Override
public void setUp() throws Exception {
super.setUp();
IdeComponents.replaceServiceWithMock(myProject, GradleProjectInfo.class);
when(GradleProjectInfo.getInstance(myProject).isBuildWithGradle()).thenReturn(true);
setUpAndroidFacetWithGradleModelWithIssue();
RenderResult result = createResultWithBrokenClass();
myRenderErrorModel = RenderErrorModelFactory.createErrorModel(result, null);
// For the isApplicable tests.
myProvider = new GradleRenderErrorContributor.GradleProvider();
}
use of com.android.tools.idea.rendering.RenderResult in project android by JetBrains.
the class LintNotificationPanel method updatePreviewImage.
private void updatePreviewImage(@Nullable NlComponent component) {
// Show the icon in the image view
if (component != null) {
// Try to get the image
int iw = myPreviewLabel.getSize().width;
int ih = myPreviewLabel.getSize().height;
if (iw == 0 || ih == 0) {
iw = 200;
ih = 200;
}
//noinspection UndesirableClassUsage
BufferedImage image = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_ARGB);
RenderResult renderResult = myScreenView.getModel().getRenderResult();
if (renderResult != null && renderResult.hasImage()) {
// Draw the component into the preview image
Graphics2D g2d = (Graphics2D) image.getGraphics();
int sx1 = component.x;
int sy1 = component.y;
int sx2 = sx1 + component.w;
int sy2 = sy1 + component.h;
int dx1 = 0;
int dy1 = 0;
int dx2 = image.getWidth();
int dy2 = image.getHeight();
int ex1 = 0;
int ey1 = 0;
int ew = image.getWidth();
int eh = image.getHeight();
if (component.isRoot()) {
int w = image.getWidth();
int h = image.getHeight();
double aspectRatio = (sx2 - sx1) / (double) (sy2 - sy1);
if (aspectRatio >= 1) {
int newH = (int) (h / aspectRatio);
dy1 += (h - newH) / 2;
h = newH;
if (w >= (sx2 - sx1)) {
// No need to scale: just buildDisplayList 1-1
dx1 = (w - (sx2 - sx1)) / 2;
w = sx2 - sx1;
dy1 = (h - (sy2 - sy1)) / 2;
h = sy2 - sy1;
}
} else {
int newW = (int) (w * aspectRatio);
dx1 += (w - newW) / 2;
w = newW;
if (h >= (sy2 - sy1)) {
// No need to scale: just buildDisplayList 1-1
dx1 = (w - (sx2 - sx1)) / 2;
w = sx2 - sx1;
dy1 = (h - (sy2 - sy1)) / 2;
h = sy2 - sy1;
}
}
dx2 = dx1 + w;
dy2 = dy1 + h;
} else {
double aspectRatio = (sx2 - sx1) / (double) (sy2 - sy1);
if (aspectRatio >= 1) {
// Include enough context
int verticalPadding = ((sx2 - sx1) - (sy2 - sy1)) / 2;
sy1 -= verticalPadding;
sy2 += verticalPadding;
double scale = (sx2 - sx1) / (double) (dx2 - dx1);
ey1 = (int) (verticalPadding / scale);
eh = (int) (component.h / scale);
} else {
int horizontalPadding = ((sy2 - sy1) - (sx2 - sx1)) / 2;
sx1 -= horizontalPadding;
sx2 += horizontalPadding;
double scale = (sy2 - sy1) / (double) (dy2 - dy1);
ex1 = (int) (horizontalPadding / scale);
ew = (int) (component.w / scale);
}
}
// Use a gradient buildDisplayList here with alpha?
//graphics.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(KEY_RENDERING, VALUE_RENDER_QUALITY);
g2d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_QUALITY);
renderResult.getRenderedImage().drawImageTo(g2d, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
if (!component.isRoot()) {
Area outside = new Area(new Rectangle2D.Double(0, 0, iw, ih));
int padding = 10;
Area area = new Area(new Ellipse2D.Double(ex1 - padding, ey1 - padding, ew + 2 * padding, eh + 2 * padding));
outside.subtract(area);
// To get anti=aliased shape clipping (e.g. soft shape clipping) we need to use an intermediate image:
GraphicsConfiguration gc = g2d.getDeviceConfiguration();
BufferedImage img = gc.createCompatibleImage(iw, ih, Transparency.TRANSLUCENT);
Graphics2D g2 = img.createGraphics();
g2.setComposite(AlphaComposite.Clear);
g2.fillRect(0, 0, iw, ih);
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
// This color is relative to the Android image being painted, not dark/light IDE theme
//noinspection UseJBColor
g2.setColor(Color.WHITE);
g2.fill(outside);
g2.setComposite(AlphaComposite.SrcAtop);
Color background = myPanel.getBackground();
if (background == null) {
background = Gray._230;
}
g2.setPaint(background);
g2.fillRect(0, 0, iw, ih);
g2.dispose();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f));
g2d.drawImage(img, 0, 0, null);
}
g2d.dispose();
}
myPreviewLabel.setIcon(new ImageIcon(image));
} else {
myPreviewLabel.setIcon(null);
}
}
use of com.android.tools.idea.rendering.RenderResult in project android by JetBrains.
the class DesignSurface method updateErrors.
/**
* When we have render errors for a given result, kick off a background computation
* of the error panel HTML, which when done will update the UI thread
*/
private void updateErrors(@Nullable final RenderResult result) {
assert result != null && result.getLogger().hasProblems();
getErrorQueue().cancelAllUpdates();
getErrorQueue().queue(new Update("errors") {
@Override
public void run() {
// Look up *current* result; a newer one could be available
final RenderResult result = myScreenView != null ? myScreenView.getResult() : null;
if (result == null) {
return;
}
RenderErrorModel model = BuildSettings.getInstance(myProject).getBuildMode() != null && result.getLogger().hasErrors() ? STILL_BUILDING_ERROR_MODEL : RenderErrorModelFactory.createErrorModel(result, DataManager.getInstance().getDataContext(myErrorPanel));
myErrorPanel.setModel(model);
setShowErrorPanel(model.getSize() != 0);
}
@Override
public boolean canEat(Update update) {
return true;
}
});
}
Aggregations