chore: improve editor

This commit is contained in:
hstyi
2025-06-29 12:08:24 +08:00
committed by hstyi
parent 70fc5e3228
commit 287f6973f0
13 changed files with 166 additions and 8 deletions

View File

@@ -4,7 +4,7 @@ plugins {
project.version = "0.0.4" project.version = "0.0.5"
dependencies { dependencies {

View File

@@ -17,15 +17,13 @@ import kotlin.io.path.absolutePathString
import kotlin.io.path.name import kotlin.io.path.name
class EditorDialog(file: Path, owner: Window, myDisposable: Disposable) : DialogWrapper(null) { class EditorDialog(file: Path, owner: Window, private val myDisposable: Disposable) : DialogWrapper(null) {
private val filename = file.name private val filename = file.name
private val filepath = File(file.absolutePathString()) private val filepath = File(file.absolutePathString())
private val editorPanel = EditorPanel(this, filepath) private val editorPanel = EditorPanel(this, filepath)
init { init {
Disposer.register(disposable, myDisposable)
size = Dimension(UIManager.getInt("Dialog.width"), UIManager.getInt("Dialog.height")) size = Dimension(UIManager.getInt("Dialog.width"), UIManager.getInt("Dialog.height"))
isModal = false isModal = false
controlsVisible = true controlsVisible = true
@@ -49,6 +47,18 @@ class EditorDialog(file: Path, owner: Window, myDisposable: Disposable) : Dialog
doCancelAction() doCancelAction()
} }
}) })
Disposer.register(myDisposable, object : Disposable {
override fun dispose() {
doCancelAction()
}
})
Disposer.register(disposable, object : Disposable {
override fun dispose() {
Disposer.dispose(myDisposable)
}
})
} }
override fun doCancelAction() { override fun doCancelAction() {

View File

@@ -2,18 +2,24 @@ package app.termora.plugins.editor
import app.termora.DocumentAdaptor import app.termora.DocumentAdaptor
import app.termora.DynamicColor import app.termora.DynamicColor
import app.termora.EnableManager
import app.termora.Icons import app.termora.Icons
import app.termora.database.DatabaseManager import app.termora.database.DatabaseManager
import com.formdev.flatlaf.FlatLaf import com.formdev.flatlaf.FlatLaf
import com.formdev.flatlaf.extras.components.FlatTextField import com.formdev.flatlaf.extras.components.FlatTextField
import com.formdev.flatlaf.extras.components.FlatToolBar import com.formdev.flatlaf.extras.components.FlatToolBar
import kotlinx.serialization.json.Json
import org.apache.commons.io.FilenameUtils import org.apache.commons.io.FilenameUtils
import org.dom4j.io.OutputFormat
import org.dom4j.io.SAXReader
import org.dom4j.io.XMLWriter
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea
import org.fife.ui.rsyntaxtextarea.SyntaxConstants import org.fife.ui.rsyntaxtextarea.SyntaxConstants
import org.fife.ui.rsyntaxtextarea.Theme import org.fife.ui.rsyntaxtextarea.Theme
import org.fife.ui.rtextarea.RTextScrollPane import org.fife.ui.rtextarea.RTextScrollPane
import org.fife.ui.rtextarea.SearchContext import org.fife.ui.rtextarea.SearchContext
import org.fife.ui.rtextarea.SearchEngine import org.fife.ui.rtextarea.SearchEngine
import org.slf4j.LoggerFactory
import java.awt.BorderLayout import java.awt.BorderLayout
import java.awt.Insets import java.awt.Insets
import java.awt.event.ActionEvent import java.awt.event.ActionEvent
@@ -21,22 +27,40 @@ import java.awt.event.KeyEvent
import java.awt.event.WindowAdapter import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent import java.awt.event.WindowEvent
import java.io.File import java.io.File
import java.io.StringReader
import java.io.StringWriter
import javax.swing.* import javax.swing.*
import javax.swing.SwingConstants.VERTICAL
import javax.swing.event.DocumentEvent import javax.swing.event.DocumentEvent
import kotlin.math.max import kotlin.math.max
class EditorPanel(private val window: JDialog, private val file: File) : JPanel(BorderLayout()) { class EditorPanel(private val window: JDialog, private val file: File) : JPanel(BorderLayout()) {
companion object {
private val log = LoggerFactory.getLogger(EditorPanel::class.java)
}
private var text = file.readText(Charsets.UTF_8) private var text = file.readText(Charsets.UTF_8)
private val layeredPane = LayeredPane() private val layeredPane = LayeredPane()
private val textArea = RSyntaxTextArea() private val textArea = RSyntaxTextArea()
private val scrollPane = RTextScrollPane(textArea) private val scrollPane = RTextScrollPane(textArea)
private val findPanel = FlatToolBar().apply { isFloatable = false } private val findPanel = FlatToolBar().apply { isFloatable = false }
private val toolbar = FlatToolBar().apply { isFloatable = false }
private val searchTextField = FlatTextField() private val searchTextField = FlatTextField()
private val closeFindPanelBtn = JButton(Icons.close) private val closeFindPanelBtn = JButton(Icons.close)
private val nextBtn = JButton(Icons.down) private val nextBtn = JButton(Icons.down)
private val prevBtn = JButton(Icons.up) private val prevBtn = JButton(Icons.up)
private val context = SearchContext() private val context = SearchContext()
private val softWrapBtn = JToggleButton(Icons.softWrap)
private val scrollUpBtn = JButton(Icons.scrollUp)
private val scrollEndBtn = JButton(Icons.scrollDown)
private val prettyBtn = JButton(Icons.reformatCode)
private val enableManager get() = EnableManager.getInstance()
private val prettyJson = Json {
prettyPrint = true
}
init { init {
initView() initView()
@@ -48,6 +72,7 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
textArea.font = textArea.font.deriveFont(DatabaseManager.getInstance().terminal.fontSize.toFloat()) textArea.font = textArea.font.deriveFont(DatabaseManager.getInstance().terminal.fontSize.toFloat())
textArea.text = text textArea.text = text
textArea.antiAliasingEnabled = true textArea.antiAliasingEnabled = true
softWrapBtn.isSelected = enableManager.getFlag("Plugins.editor.softWrap", false)
val theme = if (FlatLaf.isLafDark()) val theme = if (FlatLaf.isLafDark())
Theme.load(javaClass.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml")) Theme.load(javaClass.getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml"))
@@ -89,9 +114,13 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
else -> SyntaxConstants.SYNTAX_STYLE_NONE else -> SyntaxConstants.SYNTAX_STYLE_NONE
} }
// 只有 JSON 才可以格式化
prettyBtn.isVisible = textArea.syntaxEditingStyle == SyntaxConstants.SYNTAX_STYLE_JSON ||
textArea.syntaxEditingStyle == SyntaxConstants.SYNTAX_STYLE_XML
textArea.discardAllEdits() textArea.discardAllEdits()
scrollPane.border = BorderFactory.createMatteBorder(1, 0, 0, 0, DynamicColor.BorderColor) scrollPane.border = BorderFactory.createMatteBorder(0, 0, 0, 1, DynamicColor.BorderColor)
findPanel.isVisible = false findPanel.isVisible = false
findPanel.isOpaque = true findPanel.isOpaque = true
@@ -110,8 +139,19 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
BorderFactory.createEmptyBorder(2, 2, 2, 2) BorderFactory.createEmptyBorder(2, 2, 2, 2)
) )
toolbar.orientation = VERTICAL
toolbar.add(scrollUpBtn)
toolbar.add(prettyBtn)
toolbar.add(softWrapBtn)
toolbar.add(scrollEndBtn)
val viewPanel = JPanel(BorderLayout())
viewPanel.add(scrollPane, BorderLayout.CENTER)
viewPanel.add(toolbar, BorderLayout.EAST)
viewPanel.border = BorderFactory.createMatteBorder(1, 0, 0, 0, DynamicColor.BorderColor)
layeredPane.add(findPanel, JLayeredPane.MODAL_LAYER as Any) layeredPane.add(findPanel, JLayeredPane.MODAL_LAYER as Any)
layeredPane.add(scrollPane, JLayeredPane.DEFAULT_LAYER as Any) layeredPane.add(viewPanel, JLayeredPane.DEFAULT_LAYER as Any)
add(layeredPane, BorderLayout.CENTER) add(layeredPane, BorderLayout.CENTER)
} }
@@ -126,6 +166,13 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
} }
}) })
softWrapBtn.addActionListener {
enableManager.getFlag("Plugins.editor.softWrap", softWrapBtn.isSelected)
textArea.lineWrap = softWrapBtn.isSelected
}
scrollUpBtn.addActionListener { scrollPane.verticalScrollBar.value = 0 }
scrollEndBtn.addActionListener { scrollPane.verticalScrollBar.value = scrollPane.verticalScrollBar.maximum }
textArea.inputMap.put( textArea.inputMap.put(
KeyStroke.getKeyStroke(KeyEvent.VK_S, toolkit.menuShortcutKeyMaskEx), KeyStroke.getKeyStroke(KeyEvent.VK_S, toolkit.menuShortcutKeyMaskEx),
@@ -135,6 +182,10 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
KeyStroke.getKeyStroke(KeyEvent.VK_F, toolkit.menuShortcutKeyMaskEx), KeyStroke.getKeyStroke(KeyEvent.VK_F, toolkit.menuShortcutKeyMaskEx),
"Find" "Find"
) )
textArea.inputMap.put(
KeyStroke.getKeyStroke(KeyEvent.VK_F, toolkit.menuShortcutKeyMaskEx or KeyEvent.SHIFT_DOWN_MASK),
"Format"
)
searchTextField.inputMap.put( searchTextField.inputMap.put(
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
@@ -159,6 +210,33 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
} }
}) })
textArea.actionMap.put("Format", object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
if (textArea.syntaxEditingStyle == SyntaxConstants.SYNTAX_STYLE_JSON) {
runCatching {
val json = prettyJson.parseToJsonElement(textArea.text)
textArea.text = prettyJson.encodeToString(json)
}.onFailure {
if (log.isErrorEnabled) {
log.error(it.message, it)
}
}
} else if (textArea.syntaxEditingStyle == SyntaxConstants.SYNTAX_STYLE_XML) {
runCatching {
val document = SAXReader().read(StringReader(textArea.text))
val sw = StringWriter()
val writer = XMLWriter(sw, OutputFormat.createPrettyPrint())
writer.write(document)
textArea.text = sw.toString()
}.onFailure {
if (log.isErrorEnabled) {
log.error(it.message, it)
}
}
}
}
})
textArea.actionMap.put("Find", object : AbstractAction("Find") { textArea.actionMap.put("Find", object : AbstractAction("Find") {
override fun actionPerformed(e: ActionEvent) { override fun actionPerformed(e: ActionEvent) {
findPanel.isVisible = true findPanel.isVisible = true
@@ -185,6 +263,10 @@ class EditorPanel(private val window: JDialog, private val file: File) : JPanel(
searchTextField.addActionListener { nextBtn.doClick(0) } searchTextField.addActionListener { nextBtn.doClick(0) }
prettyBtn.addActionListener(searchTextField.actionMap.get("Format"))
prevBtn.addActionListener { search(false) } prevBtn.addActionListener { search(false) }
nextBtn.addActionListener { search(true) } nextBtn.addActionListener { search(true) }
} }

View File

@@ -33,6 +33,10 @@ object Icons {
val empty by lazy { DynamicIcon("icons/empty.svg") } val empty by lazy { DynamicIcon("icons/empty.svg") }
val changelog by lazy { DynamicIcon("icons/changelog.svg", "icons/changelog_dark.svg") } val changelog by lazy { DynamicIcon("icons/changelog.svg", "icons/changelog_dark.svg") }
val add by lazy { DynamicIcon("icons/add.svg", "icons/add_dark.svg") } val add by lazy { DynamicIcon("icons/add.svg", "icons/add_dark.svg") }
val softWrap by lazy { DynamicIcon("icons/softWrap.svg", "icons/softWrap_dark.svg") }
val scrollUp by lazy { DynamicIcon("icons/scrollUp.svg", "icons/scrollUp_dark.svg") }
val reformatCode by lazy { DynamicIcon("icons/reformatCode.svg", "icons/reformatCode_dark.svg") }
val scrollDown by lazy { DynamicIcon("icons/scrollDown.svg", "icons/scrollDown_dark.svg") }
val locate by lazy { DynamicIcon("icons/locate.svg", "icons/locate_dark.svg") } val locate by lazy { DynamicIcon("icons/locate.svg", "icons/locate_dark.svg") }
val percentage by lazy { DynamicIcon("icons/percentage.svg", "icons/percentage_dark.svg") } val percentage by lazy { DynamicIcon("icons/percentage.svg", "icons/percentage_dark.svg") }
val text by lazy { DynamicIcon("icons/text.svg", "icons/text_dark.svg") } val text by lazy { DynamicIcon("icons/text.svg", "icons/text_dark.svg") }

View File

@@ -882,6 +882,11 @@ class TransportPanel(
private inner class EditTransferListener : TransferListener, Disposable { private inner class EditTransferListener : TransferListener, Disposable {
private val transferIds = mutableSetOf<String>() private val transferIds = mutableSetOf<String>()
private val sftp get() = DatabaseManager.getInstance().sftp private val sftp get() = DatabaseManager.getInstance().sftp
private val parentDisposable = Disposer.newDisposable()
init {
Disposer.register(this, parentDisposable)
}
override fun onTransferChanged( override fun onTransferChanged(
transfer: Transfer, transfer: Transfer,
@@ -915,13 +920,22 @@ class TransportPanel(
} }
} }
val disposed = AtomicBoolean(false)
Disposer.register(disposable, object : Disposable { Disposer.register(disposable, object : Disposable {
override fun dispose() { override fun dispose() {
job.cancel() disposed.compareAndSet(false, true)
}
})
Disposer.register(parentDisposable, object : Disposable {
override fun dispose() {
job.cancel()
if (disposed.compareAndSet(false, true)) {
Disposer.dispose(disposable)
}
} }
}) })
Disposer.register(this, disposable)
} }
private fun startEditor(localPath: Path): Disposable { private fun startEditor(localPath: Path): Disposable {

View File

@@ -0,0 +1,8 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2" y="12" width="12" height="1" rx="0.5" fill="#6C707E"/>
<rect x="6" y="6" width="8" height="1" rx="0.5" fill="#6C707E"/>
<rect x="6" y="9" width="8" height="1" rx="0.5" fill="#6C707E"/>
<rect x="2" y="3" width="12" height="1" rx="0.5" fill="#6C707E"/>
<path d="M2.8 6.1C2.64849 5.98637 2.44579 5.96809 2.27639 6.05279C2.107 6.13749 2 6.31062 2 6.5V9.5C2 9.68939 2.107 9.86252 2.27639 9.94722C2.44579 10.0319 2.64849 10.0136 2.8 9.9L4.8 8.4C4.9259 8.30558 5 8.15738 5 8C5 7.84262 4.9259 7.69443 4.8 7.6L2.8 6.1Z" fill="#4682FA"/>
</svg>

After

Width:  |  Height:  |  Size: 770 B

View File

@@ -0,0 +1,8 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2" y="12" width="12" height="1" rx="0.5" fill="#CED0D6"/>
<rect x="6" y="6" width="8" height="1" rx="0.5" fill="#CED0D6"/>
<rect x="6" y="9" width="8" height="1" rx="0.5" fill="#CED0D6"/>
<rect x="2" y="3" width="12" height="1" rx="0.5" fill="#CED0D6"/>
<path d="M2.8 6.1C2.64849 5.98637 2.44579 5.96809 2.27639 6.05279C2.107 6.13749 2 6.31062 2 6.5V9.5C2 9.68939 2.107 9.86252 2.27639 9.94722C2.44579 10.0319 2.64849 10.0136 2.8 9.9L4.8 8.4C4.9259 8.30558 5 8.15738 5 8C5 7.84262 4.9259 7.69443 4.8 7.6L2.8 6.1Z" fill="#548AF7"/>
</svg>

After

Width:  |  Height:  |  Size: 770 B

View File

@@ -0,0 +1,5 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.5 3.5H5.5M1.5 8H5.5M1.5 12.5H14.5" stroke="#6C707E" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.5 3C11.7761 3 12 3.22386 12 3.5L12 9.29291L14.1465 7.14646C14.3417 6.95119 14.6583 6.9512 14.8536 7.14646C15.0488 7.34172 15.0488 7.65831 14.8536 7.85357L11.8536 10.8536C11.6583 11.0488 11.3417 11.0488 11.1464 10.8536L8.14648 7.85356C7.95121 7.6583 7.95122 7.34172 8.14648 7.14646C8.34174 6.9512 8.65832 6.9512 8.85358 7.14646L11 9.29289L11 3.5C11 3.22386 11.2239 3 11.5 3Z" fill="#6C707E"/>
</svg>

After

Width:  |  Height:  |  Size: 788 B

View File

@@ -0,0 +1,5 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.5 3.5H5.5M1.5 8H5.5M1.5 12.5H14.5" stroke="#CED0D6" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.5 3C11.7761 3 12 3.22386 12 3.5L12 9.29291L14.1464 7.14646C14.3417 6.95119 14.6583 6.9512 14.8536 7.14646C15.0488 7.34172 15.0488 7.65831 14.8536 7.85357L11.8535 10.8536C11.6583 11.0488 11.3417 11.0488 11.1464 10.8536L8.14645 7.85356C7.95118 7.6583 7.95118 7.34172 8.14645 7.14646C8.34171 6.9512 8.65829 6.9512 8.85355 7.14646L11 9.29289L11 3.5C11 3.22386 11.2238 3 11.5 3Z" fill="#CED0D6"/>
</svg>

After

Width:  |  Height:  |  Size: 788 B

View File

@@ -0,0 +1,7 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4H14.5C14.7761 4 15 3.77614 15 3.5C15 3.22386 14.7761 3 14.5 3H1.5Z" fill="#6C707E"/>
<path d="M1.5 7.5C1.22386 7.5 1 7.72386 1 8C1 8.27614 1.22386 8.5 1.5 8.5H5.5C5.77614 8.5 6 8.27614 6 8C6 7.72386 5.77614 7.5 5.5 7.5H1.5Z" fill="#6C707E"/>
<path d="M1.5 12C1.22386 12 1 12.2239 1 12.5C1 12.7761 1.22386 13 1.5 13H5.5C5.77614 13 6 12.7761 6 12.5C6 12.2239 5.77614 12 5.5 12H1.5Z" fill="#6C707E"/>
<path d="M11 12.5C11 12.7761 11.2239 13 11.5 13C11.7762 13 12 12.7761 12 12.5V6.70711L14.1464 8.85354C14.3417 9.0488 14.6583 9.0488 14.8536 8.85354C15.0488 8.65828 15.0488 8.3417 14.8536 8.14644L11.8536 5.14645C11.6583 4.95119 11.3417 4.95118 11.1465 5.14644L8.14645 8.14643C7.95119 8.34169 7.95118 8.65828 8.14644 8.85354C8.3417 9.0488 8.65829 9.04881 8.85355 8.85355L11 6.70709V12.5Z" fill="#6C707E"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,7 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4H14.5C14.7761 4 15 3.77614 15 3.5C15 3.22386 14.7761 3 14.5 3H1.5Z" fill="#CED0D6"/>
<path d="M1.5 7.5C1.22386 7.5 1 7.72386 1 8C1 8.27614 1.22386 8.5 1.5 8.5H5.5C5.77614 8.5 6 8.27614 6 8C6 7.72386 5.77614 7.5 5.5 7.5H1.5Z" fill="#CED0D6"/>
<path d="M1.5 12C1.22386 12 1 12.2239 1 12.5C1 12.7761 1.22386 13 1.5 13H5.5C5.77614 13 6 12.7761 6 12.5C6 12.2239 5.77614 12 5.5 12H1.5Z" fill="#CED0D6"/>
<path d="M11 12.5C11 12.7761 11.2239 13 11.5 13C11.7762 13 12 12.7761 12 12.5V6.70711L14.1464 8.85354C14.3417 9.0488 14.6583 9.0488 14.8536 8.85354C15.0488 8.65828 15.0488 8.3417 14.8536 8.14644L11.8536 5.14645C11.6583 4.95119 11.3417 4.95118 11.1465 5.14644L8.14645 8.14643C7.95119 8.34169 7.95118 8.65828 8.14644 8.85354C8.3417 9.0488 8.65829 9.04881 8.85355 8.85355L11 6.70709V12.5Z" fill="#CED0D6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,4 @@
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4V3ZM14.5 4C14.7761 4 15 3.77614 15 3.5C15 3.22386 14.7761 3 14.5 3V4ZM1.5 7.5C1.22386 7.5 1 7.72386 1 8C1 8.27614 1.22386 8.5 1.5 8.5V7.5ZM8.5 12.5L8.14645 12.1464L7.79289 12.5L8.14645 12.8536L8.5 12.5ZM10.8536 10.8536C11.0488 10.6583 11.0488 10.3417 10.8536 10.1464C10.6583 9.95118 10.3417 9.95118 10.1464 10.1464L10.8536 10.8536ZM10.1464 14.8536C10.3417 15.0488 10.6583 15.0488 10.8536 14.8536C11.0488 14.6583 11.0488 14.3417 10.8536 14.1464L10.1464 14.8536ZM1.5 12C1.22386 12 1 12.2239 1 12.5C1 12.7761 1.22386 13 1.5 13V12ZM5.5 13C5.77614 13 6 12.7761 6 12.5C6 12.2239 5.77614 12 5.5 12V13ZM1.5 4H14.5V3H1.5V4ZM1.5 8.5H12.25V7.5H1.5V8.5ZM12.25 12H8.5V13H12.25V12ZM8.85355 12.8536L10.8536 10.8536L10.1464 10.1464L8.14645 12.1464L8.85355 12.8536ZM8.14645 12.8536L10.1464 14.8536L10.8536 14.1464L8.85355 12.1464L8.14645 12.8536ZM1.5 13H5.5V12H1.5V13ZM12.25 13C13.7688 13 15 11.7688 15 10.25H14C14 11.2165 13.2165 12 12.25 12V13ZM12.25 8.5C13.2165 8.5 14 9.2835 14 10.25H15C15 8.73122 13.7688 7.5 12.25 7.5V8.5Z" fill="#6C707E"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,4 @@
<!-- Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4V3ZM14.5 4C14.7761 4 15 3.77614 15 3.5C15 3.22386 14.7761 3 14.5 3V4ZM1.5 7.5C1.22386 7.5 1 7.72386 1 8C1 8.27614 1.22386 8.5 1.5 8.5V7.5ZM8.5 12.5L8.14645 12.1464L7.79289 12.5L8.14645 12.8536L8.5 12.5ZM10.8536 10.8536C11.0488 10.6583 11.0488 10.3417 10.8536 10.1464C10.6583 9.95118 10.3417 9.95118 10.1464 10.1464L10.8536 10.8536ZM10.1464 14.8536C10.3417 15.0488 10.6583 15.0488 10.8536 14.8536C11.0488 14.6583 11.0488 14.3417 10.8536 14.1464L10.1464 14.8536ZM1.5 12C1.22386 12 1 12.2239 1 12.5C1 12.7761 1.22386 13 1.5 13V12ZM5.5 13C5.77614 13 6 12.7761 6 12.5C6 12.2239 5.77614 12 5.5 12V13ZM1.5 4H14.5V3H1.5V4ZM1.5 8.5H12.25V7.5H1.5V8.5ZM12.25 12H8.5V13H12.25V12ZM8.85355 12.8536L10.8536 10.8536L10.1464 10.1464L8.14645 12.1464L8.85355 12.8536ZM8.14645 12.8536L10.1464 14.8536L10.8536 14.1464L8.85355 12.1464L8.14645 12.8536ZM1.5 13H5.5V12H1.5V13ZM12.25 13C13.7688 13 15 11.7688 15 10.25H14C14 11.2165 13.2165 12 12.25 12V13ZM12.25 8.5C13.2165 8.5 14 9.2835 14 10.25H15C15 8.73122 13.7688 7.5 12.25 7.5V8.5Z" fill="#CED0D6"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB