private boolean isRelevant(PsiTreeChangeEvent event) { if (myToolWindowForm == null || !myToolWindowReady || myToolWindowDisposed) { return false; } final PsiFile fileInPreview = myToolWindowForm.getFile(); final PsiFile file = event.getFile(); if (fileInPreview == null || file == null || fileInPreview != file) { return false; } PsiElement child = event.getChild(); PsiElement parent = event.getParent(); // We can ignore edits in whitespace, and in XML error nodes, and in comments // (Note that editing text in an attribute value, including whitespace characters, // is not a PsiWhiteSpace element; it's an XmlToken of token type XML_ATTRIBUTE_VALUE_TOKEN if (child instanceof PsiWhiteSpace || child instanceof PsiErrorElement || child instanceof XmlComment || parent instanceof XmlComment) { return false; } return true; }
public boolean render() { ApplicationManager.getApplication().assertIsDispatchThread(); if (myToolWindow == null || !myToolWindow.isVisible()) { return false; } final PsiFile psiFile = myToolWindowForm.getFile(); if (psiFile == null) { return false; } final AndroidFacet facet = AndroidFacet.getInstance(psiFile); if (facet == null) { return false; } getRenderingQueue() .queue( new Update("render") { @Override public void run() { ProgressManager.getInstance() .runProcess( new Runnable() { @Override public void run() { DumbService.getInstance(myProject).waitForSmartMode(); try { doRender(facet, psiFile); } catch (Throwable e) { LOG.error(e); } synchronized (PROGRESS_LOCK) { if (myCurrentIndicator != null) { myCurrentIndicator.stop(); myCurrentIndicator = null; } } } }, new AndroidPreviewProgressIndicator(myToolWindowForm, 100)); } @Override public boolean canEat(Update update) { return true; } }); return true; }
private void initToolWindow() { myToolWindowForm = new AndroidLayoutPreviewToolWindowForm(this); final String toolWindowId = AndroidBundle.message("android.layout.preview.tool.window.title"); myToolWindow = ToolWindowManager.getInstance(myProject) .registerToolWindow(toolWindowId, false, ToolWindowAnchor.RIGHT, myProject, true); myToolWindow.setIcon(AndroidIcons.AndroidPreview); ((ToolWindowManagerEx) ToolWindowManager.getInstance(myProject)) .addToolWindowManagerListener( new ToolWindowManagerAdapter() { private boolean myVisible = false; @Override public void stateChanged() { if (myProject.isDisposed()) { return; } final ToolWindow window = ToolWindowManager.getInstance(myProject).getToolWindow(toolWindowId); if (window != null && window.isAvailable()) { final boolean visible = window.isVisible(); AndroidEditorSettings.getInstance().getGlobalState().setVisible(visible); if (visible && !myVisible) { render(); } myVisible = visible; } } }); final JPanel contentPanel = myToolWindowForm.getContentPanel(); final ContentManager contentManager = myToolWindow.getContentManager(); @SuppressWarnings("ConstantConditions") final Content content = contentManager.getFactory().createContent(contentPanel, null, false); content.setDisposer(myToolWindowForm); content.setCloseable(false); content.setPreferredFocusableComponent(contentPanel); contentManager.addContent(content); contentManager.setSelectedContent(content, true); myToolWindow.setAvailable(false, null); }
private void doRender(@NotNull final AndroidFacet facet, @NotNull final PsiFile psiFile) { if (myProject.isDisposed()) { return; } final AndroidLayoutPreviewToolWindowForm toolWindowForm = myToolWindowForm; if (toolWindowForm == null) { return; } final VirtualFile layoutXmlFile = psiFile.getVirtualFile(); if (layoutXmlFile == null) { return; } Module module = facet.getModule(); Configuration configuration = toolWindowForm.getConfiguration(); if (configuration == null) { return; } // Some types of files must be saved to disk first, because layoutlib doesn't // delegate XML parsers for non-layout files (meaning layoutlib will read the // disk contents, so we have to push any edits to disk before rendering) LayoutPullParserFactory.saveFileIfNecessary(psiFile); RenderResult result = null; synchronized (RENDERING_LOCK) { final RenderLogger logger = new RenderLogger(layoutXmlFile.getName(), module); final RenderService service = RenderService.create(facet, module, psiFile, configuration, logger, toolWindowForm); if (service != null) { service.useDesignMode(psiFile); result = service.render(); service.dispose(); } if (result == null) { result = RenderResult.createBlank(psiFile, logger); } } if (!getRenderingQueue().isEmpty()) { return; } final RenderResult renderResult = result; ApplicationManager.getApplication() .invokeLater( new Runnable() { @Override public void run() { if (!myToolWindowReady || myToolWindowDisposed) { return; } final TextEditor editor = getActiveLayoutXmlEditor(); // Must be run from read thread myToolWindowForm.setRenderResult(renderResult, editor); myToolWindowForm.updatePreviewPanel(); if (RenderPreviewMode.getCurrent() != RenderPreviewMode.NONE) { RenderPreviewManager previewManager = myToolWindowForm.getPreviewPanel().getPreviewManager(myToolWindowForm, true); if (previewManager != null) { previewManager.renderPreviews(); } } } }); }