public void recalculate() { myApplianceManager.reset(); myStorage.removeAll(); myDeferredFoldRegions.clear(); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); myApplianceManager.recalculateIfNecessary(); }
public SoftWrapModelImpl(@NotNull EditorImpl editor) { myEditor = editor; myStorage = new SoftWrapsStorage(); myPainter = new CompositeSoftWrapPainter(editor); myEditorTextRepresentationHelper = new DefaultEditorTextRepresentationHelper(editor); myDataMapper = new CachingSoftWrapDataMapper(editor, myStorage); myApplianceManager = new SoftWrapApplianceManager(myStorage, editor, myPainter, myDataMapper); myVisualSizeManager = new SoftWrapAwareVisualSizeManager(myPainter); myApplianceManager.addListener(myVisualSizeManager); myApplianceManager.addListener( new SoftWrapAwareDocumentParsingListenerAdapter() { @Override public void recalculationEnds() { for (SoftWrapChangeListener listener : mySoftWrapListeners) { listener.recalculationEnds(); } } }); myUseSoftWraps = areSoftWrapsEnabledInEditor(); myEditor.getColorsScheme().getFontPreferences().copyTo(myFontPreferences); editor.addPropertyChangeListener(this, this); myApplianceManager.addListener(myDataMapper); }
/** * We know that there are problems with incremental soft wraps cache update at the moment. Hence, * we may implement full cache reconstruction when the problem is encountered in order to avoid * customer annoyance. * * <p>However, the problems still should be fixed, hence, we report them only if dedicated flag is * set. * * <p>Current method encapsulates the logic mentioned above. * * @param task command object that which execution may trigger incremental update of update soft * wraps cache */ @SuppressWarnings({"UseOfArchaicSystemPropertyAccessors"}) private void executeSafely(SoftWrapAwareTask task) { try { task.run(true); } catch (Throwable e) { if (Boolean.getBoolean(DEBUG_PROPERTY_NAME) || ApplicationManager.getApplication().isUnitTestMode()) { String info = myEditor.dumpState(); LOG.error( String.format("Unexpected exception occurred during performing '%s'", task), e, info); } myEditor.getFoldingModel().rebuild(); myDataMapper.release(); myApplianceManager.reset(); myStorage.removeAll(); myApplianceManager.recalculateIfNecessary(); try { task.run(true); } catch (Throwable e1) { String info = myEditor.dumpState(); LOG.error( String.format("Can't perform %s even with complete soft wraps cache re-parsing", task), e1, info); myEditor.getSettings().setUseSoftWraps(false); task.run(false); } } }
/** * Configures given editor to wrap at given width, assuming characters are of given width * * @return whether any actual wraps of editor contents were created as a result of turning on soft * wraps */ @TestOnly public static boolean configureSoftWraps( Editor editor, final int visibleWidth, final int charWidthInPixels) { editor.getSettings().setUseSoftWraps(true); SoftWrapModelImpl model = (SoftWrapModelImpl) editor.getSoftWrapModel(); model.setSoftWrapPainter( new SoftWrapPainter() { @Override public int paint( @NotNull Graphics g, @NotNull SoftWrapDrawingType drawingType, int x, int y, int lineHeight) { return charWidthInPixels; } @Override public int getDrawingHorizontalOffset( @NotNull Graphics g, @NotNull SoftWrapDrawingType drawingType, int x, int y, int lineHeight) { return charWidthInPixels; } @Override public int getMinDrawingWidth(@NotNull SoftWrapDrawingType drawingType) { return charWidthInPixels; } @Override public boolean canUse() { return true; } @Override public void reinit() {} }); model.reinitSettings(); SoftWrapApplianceManager applianceManager = model.getApplianceManager(); applianceManager.setWidthProvider( new SoftWrapApplianceManager.VisibleAreaWidthProvider() { @Override public int getVisibleAreaWidth() { return visibleWidth; } }); model.setEditorTextRepresentationHelper( new DefaultEditorTextRepresentationHelper(editor) { @Override public int charWidth(char c, int fontType) { return charWidthInPixels; } }); applianceManager.registerSoftWrapIfNecessary(); return !model.getRegisteredSoftWraps().isEmpty(); }
/** * We know that there are problems with incremental soft wraps cache update at the moment. Hence, * we may implement full cache reconstruction when the problem is encountered in order to avoid * customer annoyance. * * <p>However, the problems still should be fixed, hence, we report them only if dedicated flag is * set. * * <p>Current method encapsulates the logic mentioned above. * * @param task command object that which execution may trigger incremental update of update soft * wraps cache */ @SuppressWarnings({"UseOfArchaicSystemPropertyAccessors"}) private void executeSafely(SoftWrapAwareTask task) { try { task.run(true); } catch (Throwable e) { if (Boolean.getBoolean(DEBUG_PROPERTY_NAME)) { LOG.error( String.format( "Unexpected exception occurred during performing '%s'. Current soft wraps cache: %n" + "%s%nFold regions: %s", task, myDataMapper, Arrays.toString(myEditor.getFoldingModel().fetchTopLevel())), e); } myEditor.getFoldingModel().rebuild(); myDataMapper.release(); myApplianceManager.reset(); myStorage.removeAll(); try { task.run(true); } catch (Throwable e1) { LOG.error( String.format( "Can't perform %s even with complete soft wraps cache re-parsing. Current soft wraps cache: %n" + "%s. Document:%n%s%nFold regions: %s", task, myDataMapper, myEditor.getDocument().getText(), Arrays.toString(myEditor.getFoldingModel().fetchTopLevel())), e1); myEditor.getSettings().setUseSoftWraps(false); task.run(false); } } }
/** * Encapsulates preparations for performing document dimension mapping (e.g. visual to logical * position) and answers if soft wraps-aware processing should be used (e.g. there is no need to * consider soft wraps if user configured them not to be used). * * @return <code>true</code> if soft wraps-aware processing should be used; <code>false</code> * otherwise */ private boolean prepareToMapping() { boolean useSoftWraps = myActive <= 0 && isSoftWrappingEnabled() && myEditor.getDocument().getTextLength() > 0; if (!useSoftWraps) { return false; } if (myDirty) { myApplianceManager.reset(); myDeferredFoldRegions.clear(); myDirty = false; } return myApplianceManager.recalculateIfNecessary(); }
@Override public void release() { myDataMapper.release(); myApplianceManager.release(); myStorage.removeAll(); myDeferredFoldRegions.clear(); }
@NotNull @Override public String dumpState() { return String.format( "appliance manager state: %s; soft wraps mapping info: %s", myApplianceManager.dumpState(), myDataMapper.dumpState()); }
/** * Called on editor settings change. Current model is expected to drop all cached information * about the settings if any. */ public void reinitSettings() { boolean softWrapsUsedBefore = myUseSoftWraps; myUseSoftWraps = areSoftWrapsEnabledInEditor(); int tabWidthBefore = myTabWidth; myTabWidth = EditorUtil.getTabSize(myEditor); boolean fontsChanged = false; if (!myFontPreferences.equals(myEditor.getColorsScheme().getFontPreferences()) && myEditorTextRepresentationHelper instanceof DefaultEditorTextRepresentationHelper) { fontsChanged = true; myEditor.getColorsScheme().getFontPreferences().copyTo(myFontPreferences); ((DefaultEditorTextRepresentationHelper) myEditorTextRepresentationHelper) .clearSymbolWidthCache(); myPainter.reinit(); } if ((myUseSoftWraps ^ softWrapsUsedBefore) || (tabWidthBefore >= 0 && myTabWidth != tabWidthBefore) || fontsChanged) { myApplianceManager.reset(); myDeferredFoldRegions.clear(); myStorage.removeAll(); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); } }
/** * Encapsulates preparations for performing document dimension mapping (e.g. visual to logical * position) and answers if soft wraps-aware processing should be used (e.g. there is no need to * consider soft wraps if user configured them not to be used). * * @return <code>true</code> if soft wraps-aware processing should be used; <code>false</code> * otherwise */ private boolean prepareToMapping() { if (myUpdateInProgress || myBulkUpdateInProgress || myActive > 0 || !isSoftWrappingEnabled() || myEditor.getDocument().getTextLength() <= 0) { return false; } if (myDirty) { myApplianceManager.reset(); myDeferredFoldRegions.clear(); myDirty = false; } return myApplianceManager.recalculateIfNecessary(); }
@Override public void documentChanged(DocumentEvent event) { if (myBulkUpdateInProgress) { return; } myUpdateInProgress = false; if (!isSoftWrappingEnabled()) { return; } myApplianceManager.documentChanged(event); }
@Override public void beforeDocumentChange(DocumentEvent event) { if (myBulkUpdateInProgress) { return; } myUpdateInProgress = true; if (!isSoftWrappingEnabled()) { myDirty = true; return; } myApplianceManager.beforeDocumentChange(event); }
/** * Callback method that is expected to be invoked before editor painting. * * <p>It's primary purpose is to recalculate soft wraps at least for the painted area if * necessary. */ public void registerSoftWrapsIfNecessary() { if (!isSoftWrappingEnabled()) { return; } myActive++; try { myApplianceManager.registerSoftWrapIfNecessary(); } finally { myActive--; } }
@Override public void moveTextHappened(int start, int end, int base) { if (myBulkUpdateInProgress) { return; } if (!isSoftWrappingEnabled()) { myDirty = true; return; } myApplianceManager.recalculate( Arrays.asList(new TextRange(start, end), new TextRange(base, base + end - start))); }
public SoftWrapModelImpl( @NotNull final EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter, @NotNull EditorTextRepresentationHelper representationHelper) { this( editor, storage, painter, representationHelper, new CachingSoftWrapDataMapper(editor, storage, representationHelper)); myApplianceManager.addListener(myDataMapper); }
/** * Called on editor settings change. Current model is expected to drop all cached information * about the settings if any. */ public void reinitSettings() { boolean softWrapsUsedBefore = myUseSoftWraps; EditorSettings settings = myEditor.getSettings(); myUseSoftWraps = settings.isUseSoftWraps(); if (myUseSoftWraps && (!softWrapsUsedBefore || settings.getAdditionalColumnsCount() > 0)) { myApplianceManager.reset(); myDeferredFoldRegions.clear(); myAdditionalColumnsCount = settings.getAdditionalColumnsCount(); settings.setAdditionalColumnsCount(0); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); } else if (!myUseSoftWraps && softWrapsUsedBefore) { settings.setAdditionalColumnsCount(myAdditionalColumnsCount); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); } }
public SoftWrapModelImpl( @NotNull EditorEx editor, @NotNull SoftWrapsStorage storage, @NotNull SoftWrapPainter painter, @NotNull SoftWrapApplianceManager applianceManager, @NotNull CachingSoftWrapDataMapper dataMapper) { myEditor = editor; myStorage = storage; myPainter = painter; myApplianceManager = applianceManager; myDataMapper = dataMapper; myFoldBasedApplianceStrategy = new SoftWrapFoldBasedApplianceStrategy(editor); myVisualSizeManager = new SoftWrapAwareVisualSizeManager(painter); myDocumentListeners.add(myApplianceManager); myFoldListeners.add(myApplianceManager); applianceManager.addListener(myVisualSizeManager); EditorSettings settings = myEditor.getSettings(); myAdditionalColumnsCount = settings.getAdditionalColumnsCount(); myUseSoftWraps = settings.isUseSoftWraps(); editor.addPropertyChangeListener(this); }
public void recalculate() { myApplianceManager.reset(); myStorage.removeAll(); myDeferredFoldRegions.clear(); myApplianceManager.recalculateIfNecessary(); }
@TestOnly public void setEditorTextRepresentationHelper( EditorTextRepresentationHelper editorTextRepresentationHelper) { myEditorTextRepresentationHelper = editorTextRepresentationHelper; myApplianceManager.reset(); }
@TestOnly public void setSoftWrapPainter(SoftWrapPainter painter) { myPainter = painter; myApplianceManager.setSoftWrapPainter(painter); myVisualSizeManager.setSoftWrapPainter(painter); }