use of com.android.tools.idea.uibuilder.model.NlModel in project android by JetBrains.
the class LintNotificationPanel method updateExplanation.
private void updateExplanation(@Nullable IssueData selected) {
// We have the capability to show markup text here, e.g.
// myExplanationPane.setContentType(UIUtil.HTML_MIME)
// and then use an HtmlBuilder to populate it with for
// example issue.getExplanation(HTML). However, the builtin
// HTML formatter ends up using a bunch of weird fonts etc
// so the dialog just ends up looking tacky.
String headerFontColor = HtmlBuilderHelper.getHeaderFontColor();
HtmlBuilder builder = new HtmlBuilder();
builder.openHtmlBody();
if (selected != null) {
builder.addHeading("Message: ", headerFontColor);
builder.add(selected.message).newline();
// Look for quick fixes
AndroidLintInspectionBase inspection = selected.inspection;
AndroidLintQuickFix[] quickFixes = inspection.getQuickFixes(selected.startElement, selected.endElement, selected.message);
IntentionAction[] intentions = inspection.getIntentions(selected.startElement, selected.endElement);
builder.addHeading("Suggested Fixes:", headerFontColor).newline();
builder.beginList();
for (final AndroidLintQuickFix fix : quickFixes) {
builder.listItem();
builder.addLink(fix.getName(), myLinkManager.createRunnableLink(() -> {
myPopup.cancel();
// TODO: Pull in editor context?
WriteCommandAction.runWriteCommandAction(selected.startElement.getProject(), () -> {
fix.apply(selected.startElement, selected.endElement, AndroidQuickfixContexts.BatchContext.getInstance());
});
}));
}
for (final IntentionAction fix : intentions) {
builder.listItem();
builder.addLink(fix.getText(), myLinkManager.createRunnableLink(() -> {
NlModel model = myScreenView.getModel();
Editor editor = PsiEditorUtil.Service.getInstance().findEditorByPsiElement(selected.startElement);
if (editor != null) {
editor.getCaretModel().getCurrentCaret().moveToOffset(selected.startElement.getTextOffset());
myPopup.cancel();
WriteCommandAction.runWriteCommandAction(model.getProject(), () -> {
fix.invoke(model.getProject(), editor, model.getFile());
});
}
}));
}
final SuppressLintIntentionAction suppress = new SuppressLintIntentionAction(selected.issue, selected.startElement);
builder.listItem();
builder.addLink(suppress.getText(), myLinkManager.createRunnableLink(() -> {
myPopup.cancel();
WriteCommandAction.runWriteCommandAction(selected.startElement.getProject(), () -> {
suppress.invoke(selected.startElement.getProject(), null, myScreenView.getModel().getFile());
});
}));
builder.endList();
Issue issue = selected.issue;
builder.addHeading("Priority: ", headerFontColor);
builder.addHtml(String.format("%1$d / 10", issue.getPriority()));
builder.newline();
builder.addHeading("Category: ", headerFontColor);
builder.add(issue.getCategory().getFullName());
builder.newline();
builder.addHeading("Severity: ", headerFontColor);
builder.beginSpan();
// Use converted level instead of *default* severity such that we match any user configured overrides
HighlightDisplayLevel level = selected.level;
builder.add(StringUtil.capitalize(level.getName().toLowerCase(Locale.US)));
builder.endSpan();
builder.newline();
builder.addHeading("Explanation: ", headerFontColor);
String description = issue.getBriefDescription(HTML);
builder.addHtml(description);
if (!description.isEmpty() && Character.isLetter(description.charAt(description.length() - 1))) {
builder.addHtml(".");
}
builder.newline();
String explanationHtml = issue.getExplanation(HTML);
builder.addHtml(explanationHtml);
List<String> moreInfo = issue.getMoreInfo();
builder.newline();
int count = moreInfo.size();
if (count > 1) {
builder.addHeading("More Info: ", headerFontColor);
builder.beginList();
}
for (String uri : moreInfo) {
if (count > 1) {
builder.listItem();
}
builder.addLink(uri, uri);
}
if (count > 1) {
builder.endList();
}
builder.newline();
}
builder.closeHtmlBody();
try {
myExplanationPane.read(new StringReader(builder.getHtml()), null);
HtmlBuilderHelper.fixFontStyles(myExplanationPane);
myExplanationPane.setCaretPosition(0);
} catch (IOException ignore) {
// can't happen for internal string reading
}
}
use of com.android.tools.idea.uibuilder.model.NlModel in project android by JetBrains.
the class LintNotificationPanel method hyperlinkUpdate.
// ---- Implements HyperlinkListener ----
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
JEditorPane pane = (JEditorPane) e.getSource();
if (e instanceof HTMLFrameHyperlinkEvent) {
HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e;
HTMLDocument doc = (HTMLDocument) pane.getDocument();
doc.processHTMLFrameHyperlinkEvent(evt);
return;
}
String url = e.getDescription();
NlModel model = myScreenView.getModel();
Module module = model.getModule();
PsiFile file = model.getFile();
DataContext dataContext = DataManager.getInstance().getDataContext(myScreenView.getSurface());
assert dataContext != null;
myLinkManager.handleUrl(url, module, file, dataContext, null);
}
}
use of com.android.tools.idea.uibuilder.model.NlModel in project android by JetBrains.
the class FileChooserActionListener method openDeviceChoiceDialog.
/**
* Open a dialog asking to choose a device whose dimensions match those of the image
*/
private static void openDeviceChoiceDialog(VirtualFile virtualFile, @NotNull NlProperty fileProperty, @Nullable NlProperty cropProperty) {
if (virtualFile.exists() && !virtualFile.isDirectory()) {
try {
final Image probe = PixelProbe.probe(virtualFile.getInputStream());
final BufferedImage image = probe.getMergedImage();
if (image == null) {
return;
}
final NlModel model = fileProperty.getModel();
final Configuration configuration = model.getConfiguration();
final Device device = configuration.getDevice();
if (device == null) {
return;
}
ApplicationManager.getApplication().invokeLater(() -> {
final DeviceSelectionPopup deviceSelectionPopup = new DeviceSelectionPopup(model.getProject(), configuration, image);
if (deviceSelectionPopup.showAndGet()) {
saveMockupFile(virtualFile, fileProperty, cropProperty);
}
});
} catch (IOException e1) {
LOGGER.warn("Unable to open this file\n" + e1.getMessage());
}
}
}
use of com.android.tools.idea.uibuilder.model.NlModel in project android by JetBrains.
the class IncludeTagCreator method createNewIncludedLayout.
/**
* Create a new layout that will be included as a child of the mockup component
*/
private String createNewIncludedLayout() {
AndroidFacet facet = getMockup().getComponent().getModel().getFacet();
ResourceFolderType folderType = AndroidResourceUtil.XML_FILE_RESOURCE_TYPES.get(ResourceType.LAYOUT);
XmlFile newFile = CreateResourceFileAction.createFileResource(facet, folderType, null, null, null, true, null, null, null, false);
if (newFile == null) {
return null;
}
XmlTag rootTag = newFile.getRootTag();
if (rootTag == null) {
return null;
}
NlModel nlModel = NlModel.create(getScreenView().getSurface(), newFile.getProject(), facet, newFile);
ModelListener listener = new ModelListener() {
@Override
public void modelChanged(@NotNull NlModel model) {
}
@Override
public void modelRendered(@NotNull NlModel model) {
model.removeListener(this);
if (model.getComponents().isEmpty()) {
return;
}
NlComponent component = model.getComponents().get(0);
final AttributesTransaction transaction = component.startAttributeTransaction();
addShowInAttribute(transaction);
addSizeAttributes(transaction, getAndroidBounds());
addMockupAttributes(transaction, getSelectionBounds());
WriteCommandAction.runWriteCommandAction(model.getProject(), (Computable) transaction::commit);
}
@Override
public void modelChangedOnLayout(@NotNull NlModel model, boolean animate) {
// Do nothing
}
};
nlModel.addListener(listener);
nlModel.requestRender();
return getResourceName(newFile);
}
use of com.android.tools.idea.uibuilder.model.NlModel in project android by JetBrains.
the class AbsoluteLayoutHandlerTest method createModel.
@NotNull
private NlModel createModel() {
ModelBuilder builder = model("absolute.xml", component(ABSOLUTE_LAYOUT).withBounds(0, 0, 1000, 1000).matchParentWidth().matchParentHeight().children(component(TEXT_VIEW).withBounds(100, 100, 100, 100).id("@id/myText").width("100dp").height("100dp").withAttribute("android:layout_x", "100dp").withAttribute("android:layout_y", "100dp")));
final NlModel model = builder.build();
assertEquals(1, model.getComponents().size());
assertEquals("NlComponent{tag=<AbsoluteLayout>, bounds=[0,0:1000x1000}\n" + " NlComponent{tag=<TextView>, bounds=[100,100:100x100}", NlTreeDumper.dumpTree(model.getComponents()));
format(model.getFile());
assertEquals("<AbsoluteLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" + " android:layout_width=\"match_parent\"\n" + " android:layout_height=\"match_parent\">\n" + "\n" + " <TextView\n" + " android:id=\"@id/myText\"\n" + " android:layout_width=\"100dp\"\n" + " android:layout_height=\"100dp\"\n" + " android:layout_x=\"100dp\"\n" + " android:layout_y=\"100dp\" />\n" + "\n" + "</AbsoluteLayout>\n", model.getFile().getText());
return model;
}
Aggregations