protected boolean askReloadFromDisk(final VirtualFile file, final Document document) { ApplicationManager.getApplication().assertIsDispatchThread(); if (!isDocumentUnsaved(document)) return true; String message = UIBundle.message("file.cache.conflict.message.text", file.getPresentableUrl()); if (ApplicationManager.getApplication().isUnitTestMode()) throw new RuntimeException(message); final DialogBuilder builder = new DialogBuilder((Project) null); builder.setCenterPanel(new JLabel(message, Messages.getQuestionIcon(), SwingConstants.CENTER)); builder.addOkAction().setText(UIBundle.message("file.cache.conflict.load.fs.changes.button")); builder .addCancelAction() .setText(UIBundle.message("file.cache.conflict.keep.memory.changes.button")); builder.addAction( new AbstractAction(UIBundle.message("file.cache.conflict.show.difference.button")) { @Override public void actionPerformed(ActionEvent e) { String title = UIBundle.message( "file.cache.conflict.for.file.dialog.title", file.getPresentableUrl()); final ProjectEx project = (ProjectEx) ProjectLocator.getInstance().guessProjectForFile(file); SimpleDiffRequest request = new SimpleDiffRequest(project, title); FileType fileType = file.getFileType(); String fsContent = LoadTextUtil.loadText(file).toString(); request.setContents( new SimpleContent(fsContent, fileType), new DocumentContent(project, document, fileType)); request.setContentTitles( UIBundle.message("file.cache.conflict.diff.content.file.system.content"), UIBundle.message("file.cache.conflict.diff.content.memory.content")); DialogBuilder diffBuilder = new DialogBuilder(project); DiffPanelImpl diffPanel = (DiffPanelImpl) DiffManager.getInstance() .createDiffPanel(diffBuilder.getWindow(), project, diffBuilder, null); diffPanel.getOptions().setShowSourcePolicy(DiffPanelOptions.ShowSourcePolicy.DONT_SHOW); diffBuilder.setCenterPanel(diffPanel.getComponent()); diffBuilder.setDimensionServiceKey("FileDocumentManager.FileCacheConflict"); diffPanel.setDiffRequest(request); diffBuilder .addOkAction() .setText(UIBundle.message("file.cache.conflict.save.changes.button")); diffBuilder.addCancelAction(); diffBuilder.setTitle(title); if (diffBuilder.show() == DialogWrapper.OK_EXIT_CODE) { builder.getDialogWrapper().close(DialogWrapper.CANCEL_EXIT_CODE); } } }); builder.setTitle(UIBundle.message("file.cache.conflict.dialog.title")); builder.setButtonsAlignment(SwingConstants.CENTER); builder.setHelpId("reference.dialogs.fileCacheConflict"); return builder.show() == 0; }
public final ActionGroup createPopupGroup(boolean skipHideAction) { final DefaultActionGroup group = createGearPopupGroup(); if (!ToolWindowId.PREVIEW.equals(myInfo.getId())) { group.add(myToggleContentUiTypeAction); } final DefaultActionGroup moveGroup = new DefaultActionGroup(UIBundle.message("tool.window.move.to.action.group.name"), true); final ToolWindowAnchor anchor = myInfo.getAnchor(); if (anchor != ToolWindowAnchor.TOP) { final AnAction topAction = new ChangeAnchorAction( UIBundle.message("tool.window.move.to.top.action.name"), ToolWindowAnchor.TOP); moveGroup.add(topAction); } if (anchor != ToolWindowAnchor.LEFT) { final AnAction leftAction = new ChangeAnchorAction( UIBundle.message("tool.window.move.to.left.action.name"), ToolWindowAnchor.LEFT); moveGroup.add(leftAction); } if (anchor != ToolWindowAnchor.BOTTOM) { final AnAction bottomAction = new ChangeAnchorAction( UIBundle.message("tool.window.move.to.bottom.action.name"), ToolWindowAnchor.BOTTOM); moveGroup.add(bottomAction); } if (anchor != ToolWindowAnchor.RIGHT) { final AnAction rightAction = new ChangeAnchorAction( UIBundle.message("tool.window.move.to.right.action.name"), ToolWindowAnchor.RIGHT); moveGroup.add(rightAction); } group.add(moveGroup); DefaultActionGroup resize = new DefaultActionGroup(ActionsBundle.groupText("ResizeToolWindowGroup"), true); resize.add(new ResizeToolWindowAction.Left(myToolWindow, this)); resize.add(new ResizeToolWindowAction.Right(myToolWindow, this)); resize.add(new ResizeToolWindowAction.Up(myToolWindow, this)); resize.add(new ResizeToolWindowAction.Down(myToolWindow, this)); resize.add(ActionManager.getInstance().getAction("MaximizeToolWindow")); group.add(resize); if (!skipHideAction) { group.addSeparator(); group.add(new HideAction()); } return group; }
protected JetBrainsTvAction(@NotNull @NonNls final String channel) { final String fullProductName = ApplicationNamesInfo.getInstance().getFullProductName(); getTemplatePresentation().setText(fullProductName + " TV"); getTemplatePresentation() .setDescription( UIBundle.message("welcome.screen.jetbrains.tv.action.description", fullProductName)); myUrl = JETBRAINS_TV_URL + "channel/" + channel; }
@Override public void reloadFromDisk(@NotNull final Document document) { ApplicationManager.getApplication().assertIsDispatchThread(); final VirtualFile file = getFile(document); assert file != null; if (!fireBeforeFileContentReload(file, document)) { return; } final Project project = ProjectLocator.getInstance().guessProjectForFile(file); CommandProcessor.getInstance() .executeCommand( project, new Runnable() { @Override public void run() { ApplicationManager.getApplication() .runWriteAction( new ExternalChangeAction.ExternalDocumentChange(document, project) { @Override public void run() { boolean wasWritable = document.isWritable(); DocumentEx documentEx = (DocumentEx) document; documentEx.setReadOnly(false); LoadTextUtil.setCharsetWasDetectedFromBytes(file, null); documentEx.replaceText( LoadTextUtil.loadText(file), file.getModificationStamp()); documentEx.setReadOnly(!wasWritable); } }); } }, UIBundle.message("file.cache.conflict.action"), null, UndoConfirmationPolicy.REQUEST_CONFIRMATION); myUnsavedDocuments.remove(document); myMultiCaster.fileContentReloaded(file, document); }
private static String getChooserTitle(final FileChooserDescriptor descriptor) { final String title = descriptor.getTitle(); return title != null ? title : UIBundle.message("file.chooser.default.title"); }
public boolean execute(CompileContext context) { final RunConfiguration runConfiguration = CompileStepBeforeRun.getRunConfiguration(context.getCompileScope()); if (!(runConfiguration instanceof FlexUnitRunConfiguration)) { return true; } final Ref<Boolean> isDumb = new Ref<>(false); final RuntimeConfigurationException validationError = ApplicationManager.getApplication() .runReadAction( new NullableComputable<RuntimeConfigurationException>() { public RuntimeConfigurationException compute() { if (DumbService.getInstance(myProject).isDumb()) { isDumb.set(true); return null; } try { runConfiguration.checkConfiguration(); return null; } catch (RuntimeConfigurationException e) { return e; } } }); if (isDumb.get()) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("dumb.mode.flex.unit.warning"), null, -1, -1); return false; } if (validationError != null) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("configuration.not.valid", validationError.getMessage()), null, -1, -1); return false; } int flexUnitPort = ServerConnectionBase.getFreePort(FLEX_UNIT_PORT_START, PORTS_ATTEMPT_NUMBER); if (flexUnitPort == -1) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("no.free.port"), null, -1, -1); return false; } final int socketPolicyPort; if (SystemInfo.isWindows && ServerConnectionBase.tryPort(SwfPolicyFileConnection.DEFAULT_PORT)) { socketPolicyPort = SwfPolicyFileConnection.DEFAULT_PORT; } else { socketPolicyPort = ServerConnectionBase.getFreePort(SWC_POLICY_PORT_START, PORTS_ATTEMPT_NUMBER); } if (socketPolicyPort == -1) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("no.free.port"), null, -1, -1); return false; } final FlexUnitRunnerParameters params = ((FlexUnitRunConfiguration) runConfiguration).getRunnerParameters(); params.setPort(flexUnitPort); params.setSocketPolicyPort(socketPolicyPort); final Ref<Module> moduleRef = new Ref<>(); final Ref<FlexBuildConfiguration> bcRef = new Ref<>(); final Ref<FlexUnitSupport> supportRef = new Ref<>(); ApplicationManager.getApplication() .runReadAction( () -> { if (DumbService.getInstance(myProject).isDumb()) return; try { final Pair<Module, FlexBuildConfiguration> moduleAndBC = params.checkAndGetModuleAndBC(myProject); moduleRef.set(moduleAndBC.first); bcRef.set(moduleAndBC.second); supportRef.set(FlexUnitSupport.getSupport(moduleAndBC.second, moduleAndBC.first)); } catch (RuntimeConfigurationError e) { // already checked above, can't happen throw new RuntimeException(e); } }); final Module module = moduleRef.get(); final FlexBuildConfiguration bc = bcRef.get(); final FlexUnitSupport support = supportRef.get(); if (bc == null || support == null) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("dumb.mode.flex.unit.warning"), null, -1, -1); return false; } final GlobalSearchScope moduleScope = GlobalSearchScope.moduleScope(module); StringBuilder imports = new StringBuilder(); StringBuilder code = new StringBuilder(); final boolean flexUnit4; switch (params.getScope()) { case Class: { final Ref<Boolean> isFlexUnit1Suite = new Ref<>(); final Ref<Boolean> isSuite = new Ref<>(); Set<String> customRunners = ApplicationManager.getApplication() .runReadAction( new NullableComputable<Set<String>>() { public Set<String> compute() { if (DumbService.getInstance(myProject).isDumb()) return null; Set<String> result = new THashSet<>(); final JSClass clazz = (JSClass) ActionScriptClassResolver.findClassByQNameStatic( params.getClassName(), moduleScope); collectCustomRunners(result, clazz, support, null); isFlexUnit1Suite.set(support.isFlexUnit1SuiteSubclass(clazz)); isSuite.set(support.isSuite(clazz)); return result; } }); if (customRunners == null) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("dumb.mode.flex.unit.warning"), null, -1, -1); return false; } // FlexUnit4 can't run FlexUnit1 TestSuite subclasses, fallback to FlexUnit1 runner flexUnit4 = support.flexUnit4Present && !isFlexUnit1Suite.get(); generateImportCode(imports, params.getClassName(), customRunners); generateTestClassCode(code, params.getClassName(), customRunners, isSuite.get()); } break; case Method: { Set<String> customRunners = ApplicationManager.getApplication() .runReadAction( new NullableComputable<Set<String>>() { public Set<String> compute() { if (DumbService.getInstance(myProject).isDumb()) return null; Set<String> result = new THashSet<>(); final JSClass clazz = (JSClass) ActionScriptClassResolver.findClassByQNameStatic( params.getClassName(), moduleScope); collectCustomRunners(result, clazz, support, null); return result; } }); if (customRunners == null) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("dumb.mode.flex.unit.warning"), null, -1, -1); return false; } flexUnit4 = support.flexUnit4Present; generateImportCode(imports, params.getClassName(), customRunners); generateTestMethodCode( code, params.getClassName(), params.getMethodName(), customRunners); } break; case Package: { final Collection<Pair<String, Set<String>>> classes = ApplicationManager.getApplication() .runReadAction( new NullableComputable<Collection<Pair<String, Set<String>>>>() { public Collection<Pair<String, Set<String>>> compute() { if (DumbService.getInstance(myProject).isDumb()) return null; final Collection<Pair<String, Set<String>>> result = new ArrayList<>(); JSPackageIndex.processElementsInScopeRecursive( params.getPackageName(), new JSPackageIndex.PackageQualifiedElementsProcessor() { public boolean process( String qualifiedName, JSPackageIndexInfo.Kind kind, boolean isPublic) { if (kind == JSPackageIndexInfo.Kind.CLASS) { PsiElement clazz = ActionScriptClassResolver.findClassByQNameStatic( qualifiedName, moduleScope); if (clazz instanceof JSClass && support.isTestClass((JSClass) clazz, false)) { Set<String> customRunners = new THashSet<>(); collectCustomRunners( customRunners, (JSClass) clazz, support, null); result.add( Pair.create( ((JSClass) clazz).getQualifiedName(), customRunners)); } } return true; } }, moduleScope, myProject); return result; } }); if (classes == null) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("dumb.mode.flex.unit.warning"), null, -1, -1); return false; } if (classes.isEmpty()) { String message = MessageFormat.format("No tests found in package ''{0}''", params.getPackageName()); context.addMessage(CompilerMessageCategory.WARNING, message, null, -1, -1); return false; } flexUnit4 = support.flexUnit4Present; for (Pair<String, Set<String>> classAndRunner : classes) { generateImportCode(imports, classAndRunner.first, classAndRunner.second); generateTestClassCode(code, classAndRunner.first, classAndRunner.second, false); } } break; default: flexUnit4 = false; assert false : "Unknown scope: " + params.getScope(); } if (!flexUnit4 && bc.isPureAs()) { context.addMessage( CompilerMessageCategory.ERROR, FlexBundle.message("cant.execute.flexunit1.for.pure.as.bc"), null, -1, -1); } String launcherText; try { launcherText = getLauncherTemplate(bc); } catch (IOException e) { context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1); return false; } final boolean desktop = bc.getTargetPlatform() == TargetPlatform.Desktop; if (desktop) { generateImportCode(imports, "flash.desktop.NativeApplication"); } launcherText = replace(launcherText, "/*imports*/", imports.toString()); launcherText = replace( launcherText, "/*test_runner*/", flexUnit4 ? FlexCommonUtils.FLEXUNIT_4_TEST_RUNNER : FlexCommonUtils.FLEXUNIT_1_TEST_RUNNER); launcherText = replace(launcherText, "/*code*/", code.toString()); launcherText = replace(launcherText, "/*port*/", String.valueOf(flexUnitPort)); launcherText = replace(launcherText, "/*socketPolicyPort*/", String.valueOf(socketPolicyPort)); launcherText = replace(launcherText, "/*module*/", module.getName()); if (!bc.isPureAs()) { final FlexUnitRunnerParameters.OutputLogLevel logLevel = params.getOutputLogLevel(); launcherText = replace(launcherText, "/*isLogEnabled*/", logLevel != null ? "1" : "0"); launcherText = replace( launcherText, "/*logLevel*/", logLevel != null ? logLevel.getFlexConstant() : FlexUnitRunnerParameters.OutputLogLevel.All.getFlexConstant()); } final File tmpDir = new File(getPathToFlexUnitTempDirectory(myProject)); boolean ok = true; if (tmpDir.isFile()) ok &= FileUtil.delete(tmpDir); if (!tmpDir.isDirectory()) ok &= tmpDir.mkdirs(); if (!ok) { final String message = UIBundle.message( "create.new.folder.could.not.create.folder.error.message", FileUtil.toSystemDependentName(tmpDir.getPath())); context.addMessage(CompilerMessageCategory.ERROR, message, null, -1, -1); return false; } final String fileName = FlexCommonUtils.FLEX_UNIT_LAUNCHER + FlexCommonUtils.getFlexUnitLauncherExtension(bc.getNature()); final File launcherFile = new File(tmpDir, fileName); FileUtil.delete(launcherFile); try { FileUtil.writeToFile(launcherFile, launcherText); } catch (IOException e) { context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1); return false; } context.putUserData(FILES_TO_DELETE, Collections.singletonList(launcherFile.getPath())); return true; }
public String getTooltipText() { return isReadonlyApplicable() ? UIBundle.message("read.only.attr.panel.double.click.to.toggle.attr.tooltip.text") : null; }
private void setOrientation(boolean isVerticalSplit) { removeAll(); if (!myShowDividerControls) { return; } int xMask = isVerticalSplit ? 1 : 0; int yMask = isVerticalSplit ? 0 : 1; Icon glueIcon = isVerticalSplit ? AllIcons.General.SplitGlueV : AllIcons.General.SplitCenterH; int glueFill = isVerticalSplit ? GridBagConstraints.VERTICAL : GridBagConstraints.HORIZONTAL; add( new JLabel(glueIcon), new GridBagConstraints( 0, 0, 1, 1, 0, 0, isVerticalSplit ? GridBagConstraints.EAST : GridBagConstraints.NORTH, glueFill, new Insets(0, 0, 0, 0), 0, 0)); JLabel splitDownlabel = new JLabel(isVerticalSplit ? AllIcons.General.SplitDown : AllIcons.General.SplitRight); splitDownlabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); splitDownlabel.setToolTipText( isVerticalSplit ? UIBundle.message("splitter.down.tooltip.text") : UIBundle.message("splitter.right.tooltip.text")); new ClickListener() { @Override public boolean onClick(@NotNull MouseEvent e, int clickCount) { if (myInnerComponent != null) { final int income = myVerticalSplit ? myInnerComponent.getHeight() : myInnerComponent.getWidth(); if (myIsFirst) { setFirstSize(myFirstSize + income); } else { setLastSize(myLastSize + income); } } return true; } }.installOn(splitDownlabel); add( splitDownlabel, new GridBagConstraints( isVerticalSplit ? 1 : 0, isVerticalSplit ? 0 : 5, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); // add( new JLabel(glueIcon), new GridBagConstraints( 2 * xMask, 2 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, new Insets(0, 0, 0, 0), 0, 0)); JLabel splitCenterlabel = new JLabel( isVerticalSplit ? AllIcons.General.SplitCenterV : AllIcons.General.SplitCenterH); splitCenterlabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); splitCenterlabel.setToolTipText(UIBundle.message("splitter.center.tooltip.text")); new ClickListener() { @Override public boolean onClick(@NotNull MouseEvent e, int clickCount) { center(); return true; } }.installOn(splitCenterlabel); add( splitCenterlabel, new GridBagConstraints( 3 * xMask, 3 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); add( new JLabel(glueIcon), new GridBagConstraints( 4 * xMask, 4 * yMask, 1, 1, 0, 0, GridBagConstraints.CENTER, glueFill, new Insets(0, 0, 0, 0), 0, 0)); // JLabel splitUpLabel = new JLabel(isVerticalSplit ? AllIcons.General.SplitUp : AllIcons.General.SplitLeft); splitUpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); splitUpLabel.setToolTipText( isVerticalSplit ? UIBundle.message("splitter.up.tooltip.text") : UIBundle.message("splitter.left.tooltip.text")); new ClickListener() { @Override public boolean onClick(@NotNull MouseEvent e, int clickCount) { if (myInnerComponent != null) { final int income = myVerticalSplit ? myInnerComponent.getHeight() : myInnerComponent.getWidth(); if (myIsFirst) { setFirstSize(myFirstSize + income); } else { setLastSize(myLastSize + income); } } return true; } }.installOn(splitUpLabel); add( splitUpLabel, new GridBagConstraints( isVerticalSplit ? 5 : 0, isVerticalSplit ? 0 : 1, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); add( new JLabel(glueIcon), new GridBagConstraints( 6 * xMask, 6 * yMask, 1, 1, 0, 0, isVerticalSplit ? GridBagConstraints.WEST : GridBagConstraints.SOUTH, glueFill, new Insets(0, 0, 0, 0), 0, 0)); }
public HideAction() { copyFrom(ActionManager.getInstance().getAction(HIDE_ACTIVE_WINDOW_ACTION_ID)); getTemplatePresentation().setText(UIBundle.message("tool.window.hide.action.name")); }
public abstract class StatusText { public static final SimpleTextAttributes DEFAULT_ATTRIBUTES = SimpleTextAttributes.GRAYED_ATTRIBUTES; public static final String DEFAULT_EMPTY_TEXT = UIBundle.message("message.nothingToShow"); @Nullable private Component myOwner; private Component myMouseTarget; private final MouseMotionListener myMouseMotionListener; private final ClickListener myClickListener; private boolean myIsDefaultText; private String myText = ""; protected final SimpleColoredComponent myComponent = new SimpleColoredComponent(); private final List<ActionListener> myClickListeners = new ArrayList<ActionListener>(); private boolean myHasActiveClickListeners; // calculated field for performance optimization protected StatusText(JComponent owner) { this(); attachTo(owner); } public StatusText() { myClickListener = new ClickListener() { @Override public boolean onClick(@NotNull MouseEvent e, int clickCount) { if (e.getButton() == MouseEvent.BUTTON1 && clickCount == 1) { ActionListener actionListener = findActionListenerAt(e.getPoint()); if (actionListener != null) { actionListener.actionPerformed(new ActionEvent(this, 0, "")); return true; } } return false; } }; myMouseMotionListener = new MouseAdapter() { private Cursor myOriginalCursor; @Override public void mouseMoved(final MouseEvent e) { if (isStatusVisible()) { if (findActionListenerAt(e.getPoint()) != null) { if (myOriginalCursor == null) { myOriginalCursor = myMouseTarget.getCursor(); myMouseTarget.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } } else if (myOriginalCursor != null) { myMouseTarget.setCursor(myOriginalCursor); myOriginalCursor = null; } } } }; myComponent.setOpaque(false); myComponent.setFont(UIUtil.getLabelFont()); setText(DEFAULT_EMPTY_TEXT, DEFAULT_ATTRIBUTES); myIsDefaultText = true; } public void attachTo(@Nullable Component owner) { attachTo(owner, owner); } public void attachTo(@Nullable Component owner, @Nullable Component mouseTarget) { if (myMouseTarget != null) { myClickListener.uninstall(myMouseTarget); myMouseTarget.removeMouseMotionListener(myMouseMotionListener); } myOwner = owner; myMouseTarget = mouseTarget; if (myMouseTarget != null) { myClickListener.installOn(myMouseTarget); myMouseTarget.addMouseMotionListener(myMouseMotionListener); } } protected abstract boolean isStatusVisible(); @Nullable private ActionListener findActionListenerAt(Point point) { if (!myHasActiveClickListeners || !isStatusVisible()) return null; point = SwingUtilities.convertPoint(myMouseTarget, point, myOwner); Rectangle b = getTextComponentBound(); if (b.contains(point)) { int index = myComponent.findFragmentAt(point.x - b.x); if (index >= 0 && index < myClickListeners.size()) { return myClickListeners.get(index); } } return null; } protected Rectangle getTextComponentBound() { Rectangle ownerRec = myOwner == null ? new Rectangle(0, 0, 0, 0) : myOwner.getBounds(); Dimension size = myComponent.getPreferredSize(); int x = (ownerRec.width - size.width) / 2; int y = (ownerRec.height - size.height) / 3; return new Rectangle(x, y, size.width, size.height); } @NotNull public String getText() { return myText; } public StatusText setText(String text) { return setText(text, DEFAULT_ATTRIBUTES); } public StatusText setText(String text, SimpleTextAttributes attrs) { return clear().appendText(text, attrs); } public StatusText clear() { myText = ""; myComponent.clear(); myClickListeners.clear(); myHasActiveClickListeners = false; if (myOwner != null && isStatusVisible()) myOwner.repaint(); return this; } public StatusText appendText(String text) { return appendText(text, DEFAULT_ATTRIBUTES); } public StatusText appendText(String text, SimpleTextAttributes attrs) { return appendText(text, attrs, null); } public StatusText appendText(String text, SimpleTextAttributes attrs, ActionListener listener) { if (myIsDefaultText) { clear(); myIsDefaultText = false; } myText += text; myComponent.append(text, attrs); myClickListeners.add(listener); if (listener != null) { myHasActiveClickListeners = true; } if (myOwner != null && isStatusVisible()) myOwner.repaint(); return this; } public void paint(Component owner, Graphics g) { if (!isStatusVisible()) return; if (owner == myOwner) { doPaintStatusText(g, getTextComponentBound()); } else { paintOnComponentUnderViewport(owner, g); } } private void paintOnComponentUnderViewport(Component component, Graphics g) { JBViewport viewport = ObjectUtils.tryCast(myOwner, JBViewport.class); if (viewport == null || viewport.getView() != component || viewport.isPaintingNow()) return; // We're painting a component which has a viewport as it's ancestor. // As the viewport paints status text, we'll erase it, so we need to schedule a repaint for the // viewport with status text's bounds. // But it causes flicker, so we paint status text over the component first and then schedule the // viewport repaint. Rectangle textBoundsInViewport = getTextComponentBound(); int xInOwner = textBoundsInViewport.x - component.getX(); int yInOwner = textBoundsInViewport.y - component.getY(); Rectangle textBoundsInOwner = new Rectangle(xInOwner, yInOwner, textBoundsInViewport.width, textBoundsInViewport.height); doPaintStatusText(g, textBoundsInOwner); viewport.repaint(textBoundsInViewport); } private void doPaintStatusText(Graphics g, Rectangle textComponentBounds) { myComponent.setBounds(0, 0, textComponentBounds.width, textComponentBounds.height); Graphics2D g2 = (Graphics2D) g.create( textComponentBounds.x, textComponentBounds.y, textComponentBounds.width, textComponentBounds.height); myComponent.paint(g2); g2.dispose(); } @NotNull public SimpleColoredComponent getComponent() { return myComponent; } public Dimension getPreferredSize() { return myComponent.getPreferredSize(); } }