editor status bar with behaviour
This commit is contained in:
parent
eb2520fa40
commit
e82d3e90b4
@ -101,7 +101,7 @@
|
||||
}
|
||||
|
||||
.editor-workspace-status-chip-type-pbs {
|
||||
-fx-background-color: #1e2d3b;
|
||||
-fx-border-color: #4aa3ff;
|
||||
-fx-text-fill: #dce9f8;
|
||||
-fx-background-color: #2c2140;
|
||||
-fx-border-color: #a47dff;
|
||||
-fx-text-fill: #efe6ff;
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class EditorStatusBar extends HBox {
|
||||
private static final String DEFAULT_INDENTATION = "Spaces: 4";
|
||||
private final HBox breadcrumb = new HBox(6);
|
||||
private final Label position = new Label();
|
||||
private final Label lineSeparator = new Label();
|
||||
@ -61,9 +62,8 @@ public final class EditorStatusBar extends HBox {
|
||||
final EditorDocumentPresentation presentation) {
|
||||
showBreadcrumb(projectReference, fileBuffer.path());
|
||||
showMetadata(true);
|
||||
bindDefault(position, I18n.CODE_EDITOR_STATUS_POSITION);
|
||||
setText(lineSeparator, fileBuffer.lineSeparator());
|
||||
bindDefault(indentation, I18n.CODE_EDITOR_STATUS_INDENTATION);
|
||||
showPosition(fileBuffer.editable(), 1, 1);
|
||||
showDocumentFormatting(fileBuffer.lineSeparator(), fileBuffer.content());
|
||||
setText(language, fileBuffer.typeId());
|
||||
EditorDocumentPresentationStyles.applyToStatusChip(language, presentation);
|
||||
showAccessMode(fileBuffer.readOnly());
|
||||
@ -72,7 +72,7 @@ public final class EditorStatusBar extends HBox {
|
||||
public void showPlaceholder(final EditorDocumentPresentation presentation) {
|
||||
breadcrumb.getChildren().clear();
|
||||
showMetadata(false);
|
||||
bindDefault(position, I18n.CODE_EDITOR_STATUS_POSITION);
|
||||
showPosition(false, 1, 1);
|
||||
bindDefault(lineSeparator, I18n.CODE_EDITOR_STATUS_LINE_SEPARATOR);
|
||||
bindDefault(indentation, I18n.CODE_EDITOR_STATUS_INDENTATION);
|
||||
bindDefault(language, I18n.CODE_EDITOR_STATUS_LANGUAGE);
|
||||
@ -81,6 +81,18 @@ public final class EditorStatusBar extends HBox {
|
||||
accessMode.getStyleClass().removeAll("editor-workspace-status-chip-editable", "editor-workspace-status-chip-read-only");
|
||||
}
|
||||
|
||||
public void showCaretPosition(final int line, final int column) {
|
||||
if (!position.isManaged()) {
|
||||
return;
|
||||
}
|
||||
setText(position, line + ":" + column);
|
||||
}
|
||||
|
||||
public void showDocumentFormatting(final String separator, final String content) {
|
||||
setText(lineSeparator, separator);
|
||||
setText(indentation, detectIndentation(content));
|
||||
}
|
||||
|
||||
private void bindDefault(final Label label, final I18n key) {
|
||||
bindText(label, key);
|
||||
}
|
||||
@ -168,13 +180,21 @@ public final class EditorStatusBar extends HBox {
|
||||
}
|
||||
|
||||
private void showMetadata(final boolean visible) {
|
||||
setVisibleManaged(position, visible);
|
||||
setVisibleManaged(lineSeparator, visible);
|
||||
setVisibleManaged(indentation, visible);
|
||||
setVisibleManaged(language, visible);
|
||||
setVisibleManaged(accessMode, visible);
|
||||
}
|
||||
|
||||
private void showPosition(final boolean visible, final int line, final int column) {
|
||||
setVisibleManaged(position, visible);
|
||||
if (!visible) {
|
||||
bindDefault(position, I18n.CODE_EDITOR_STATUS_POSITION);
|
||||
return;
|
||||
}
|
||||
setText(position, line + ":" + column);
|
||||
}
|
||||
|
||||
private void showAccessMode(final boolean readOnlyMode) {
|
||||
accessMode.getChildren().setAll(readOnlyMode
|
||||
? EditorWorkspaceIcons.lockClosed()
|
||||
@ -195,4 +215,58 @@ public final class EditorStatusBar extends HBox {
|
||||
label.getStyleClass().add("editor-workspace-status-chip");
|
||||
}
|
||||
}
|
||||
|
||||
private String detectIndentation(final String content) {
|
||||
final String normalized = content == null ? "" : content.replace("\r\n", "\n").replace('\r', '\n');
|
||||
int spaceGcd = 0;
|
||||
boolean sawTabs = false;
|
||||
for (final String line : normalized.split("\n", -1)) {
|
||||
if (line.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
int spaces = 0;
|
||||
int tabs = 0;
|
||||
while (spaces + tabs < line.length()) {
|
||||
final char ch = line.charAt(spaces + tabs);
|
||||
if (ch == ' ') {
|
||||
if (tabs > 0) {
|
||||
spaces = 0;
|
||||
break;
|
||||
}
|
||||
spaces++;
|
||||
continue;
|
||||
}
|
||||
if (ch == '\t') {
|
||||
tabs++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (tabs > 0 && spaces == 0) {
|
||||
sawTabs = true;
|
||||
continue;
|
||||
}
|
||||
if (spaces > 1) {
|
||||
spaceGcd = spaceGcd == 0 ? spaces : gcd(spaceGcd, spaces);
|
||||
}
|
||||
}
|
||||
if (sawTabs) {
|
||||
return "Tabs: 1";
|
||||
}
|
||||
if (spaceGcd > 0) {
|
||||
return "Spaces: " + spaceGcd;
|
||||
}
|
||||
return DEFAULT_INDENTATION;
|
||||
}
|
||||
|
||||
private int gcd(final int left, final int right) {
|
||||
int a = Math.abs(left);
|
||||
int b = Math.abs(right);
|
||||
while (b != 0) {
|
||||
final int next = a % b;
|
||||
a = b;
|
||||
b = next;
|
||||
}
|
||||
return a == 0 ? 1 : a;
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,8 +75,11 @@ public final class EditorWorkspace extends Workspace {
|
||||
codeArea.setEditable(false);
|
||||
codeArea.setWrapText(false);
|
||||
codeArea.textProperty().addListener((ignored, previous, current) -> syncActiveDocumentToVfs(current));
|
||||
codeArea.caretPositionProperty().addListener((ignored, previous, current) ->
|
||||
updateActiveGuides(current == null ? 0 : current.intValue()));
|
||||
codeArea.caretPositionProperty().addListener((ignored, previous, current) -> {
|
||||
final int caretOffset = current == null ? 0 : current.intValue();
|
||||
updateActiveGuides(caretOffset);
|
||||
refreshStatusBarCaret();
|
||||
});
|
||||
codeArea.getStyleClass().add("editor-workspace-code-area");
|
||||
codeArea.addEventFilter(KeyEvent.KEY_PRESSED, this::guardInlineHintMutation);
|
||||
codeArea.addEventFilter(KeyEvent.KEY_TYPED, this::guardInlineHintMutation);
|
||||
@ -229,6 +232,7 @@ public final class EditorWorkspace extends Workspace {
|
||||
EditorDocumentPresentationStyles.applyToCodeArea(codeArea, presentation);
|
||||
refreshCommandSurfaces(fileBuffer);
|
||||
statusBar.showFile(projectReference, fileBuffer, presentation);
|
||||
refreshStatusBarCaret();
|
||||
refreshSemanticOutline(fileBuffer, analysis);
|
||||
}
|
||||
|
||||
@ -370,6 +374,7 @@ public final class EditorWorkspace extends Workspace {
|
||||
final String sourceContent = inlineHintProjection.stripDecorations(content);
|
||||
final VfsDocumentOpenResult.VfsTextDocument updatedDocument = vfsProjectDocument.updateDocument(activeFile.path(), sourceContent);
|
||||
openFileSession.open(bufferFrom(updatedDocument));
|
||||
statusBar.showDocumentFormatting(updatedDocument.lineSeparator(), updatedDocument.content());
|
||||
tabStrip.showOpenFiles(
|
||||
openFileSession.openFiles(),
|
||||
openFileSession.activeFile().map(EditorOpenFileBuffer::path).orElse(null));
|
||||
@ -473,6 +478,14 @@ public final class EditorWorkspace extends Workspace {
|
||||
refreshParagraphGraphics();
|
||||
}
|
||||
|
||||
private void refreshStatusBarCaret() {
|
||||
openFileSession.activeFile()
|
||||
.filter(EditorOpenFileBuffer::editable)
|
||||
.ifPresent(ignored -> statusBar.showCaretPosition(
|
||||
codeArea.getCurrentParagraph() + 1,
|
||||
codeArea.getCaretColumn() + 1));
|
||||
}
|
||||
|
||||
private void guardInlineHintMutation(final KeyEvent event) {
|
||||
if (syncingEditor || !codeArea.isEditable()) {
|
||||
return;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user