feat: 支持自定义工具栏
@@ -20,7 +20,7 @@ object Actions {
|
||||
/**
|
||||
* 关键词高亮
|
||||
*/
|
||||
const val KEYWORD_HIGHLIGHT_EVERYWHERE = "KeywordHighlightAction"
|
||||
const val KEYWORD_HIGHLIGHT = "KeywordHighlightAction"
|
||||
|
||||
/**
|
||||
* Key manager
|
||||
|
||||
351
src/main/kotlin/app/termora/CustomizeToolBarDialog.kt
Normal file
@@ -0,0 +1,351 @@
|
||||
package app.termora
|
||||
|
||||
import app.termora.Application.ohMyJson
|
||||
import app.termora.db.Database
|
||||
import com.jgoodies.forms.builder.FormBuilder
|
||||
import com.jgoodies.forms.layout.FormLayout
|
||||
import kotlinx.serialization.encodeToString
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import org.jdesktop.swingx.action.ActionManager
|
||||
import java.awt.Component
|
||||
import java.awt.Dimension
|
||||
import java.awt.Window
|
||||
import java.awt.event.WindowAdapter
|
||||
import java.awt.event.WindowEvent
|
||||
import javax.swing.*
|
||||
import javax.swing.event.ListDataEvent
|
||||
import javax.swing.event.ListDataListener
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class CustomizeToolBarDialog(
|
||||
owner: Window,
|
||||
private val toolbar: TermoraToolBar
|
||||
) : DialogWrapper(owner) {
|
||||
|
||||
private val moveTopBtn = JButton(Icons.moveUp)
|
||||
private val moveBottomBtn = JButton(Icons.moveDown)
|
||||
private val upBtn = JButton(Icons.up)
|
||||
private val downBtn = JButton(Icons.down)
|
||||
|
||||
private val leftBtn = JButton(Icons.left)
|
||||
private val rightBtn = JButton(Icons.right)
|
||||
private val allToLeftBtn = JButton(Icons.applyNotConflictsRight)
|
||||
private val allToRightBtn = JButton(Icons.applyNotConflictsLeft)
|
||||
|
||||
private val leftList = ToolBarActionList()
|
||||
private val rightList = ToolBarActionList()
|
||||
private val actionManager get() = ActionManager.getInstance()
|
||||
|
||||
private var isOk = false
|
||||
|
||||
init {
|
||||
size = Dimension(UIManager.getInt("Dialog.width") - 150, UIManager.getInt("Dialog.height") - 100)
|
||||
isModal = true
|
||||
controlsVisible = false
|
||||
isResizable = false
|
||||
title = I18n.getString("termora.toolbar.customize-toolbar")
|
||||
setLocationRelativeTo(null)
|
||||
|
||||
moveTopBtn.isEnabled = false
|
||||
moveBottomBtn.isEnabled = false
|
||||
downBtn.isEnabled = false
|
||||
upBtn.isEnabled = false
|
||||
|
||||
leftBtn.isEnabled = false
|
||||
rightBtn.isEnabled = false
|
||||
|
||||
initEvents()
|
||||
|
||||
init()
|
||||
}
|
||||
|
||||
|
||||
override fun createCenterPanel(): JComponent {
|
||||
|
||||
allToLeftBtn.isEnabled = !rightList.model.isEmpty
|
||||
allToRightBtn.isEnabled = !leftList.model.isEmpty
|
||||
|
||||
val box = JToolBar(JToolBar.VERTICAL)
|
||||
box.add(Box.createVerticalStrut(leftList.fixedCellHeight))
|
||||
box.add(rightBtn)
|
||||
box.add(leftBtn)
|
||||
box.add(Box.createVerticalGlue())
|
||||
box.add(allToRightBtn)
|
||||
box.add(allToLeftBtn)
|
||||
box.add(Box.createVerticalStrut(leftList.fixedCellHeight))
|
||||
|
||||
val box2 = JToolBar(JToolBar.VERTICAL)
|
||||
box2.add(Box.createVerticalStrut(leftList.fixedCellHeight))
|
||||
box2.add(moveTopBtn)
|
||||
box2.add(upBtn)
|
||||
box2.add(Box.createVerticalGlue())
|
||||
box2.add(downBtn)
|
||||
box2.add(moveBottomBtn)
|
||||
box2.add(Box.createVerticalStrut(leftList.fixedCellHeight))
|
||||
|
||||
|
||||
return FormBuilder.create().debug(false)
|
||||
.border(BorderFactory.createMatteBorder(1, 0, 0, 0, DynamicColor.BorderColor))
|
||||
.layout(FormLayout("default:grow, pref, default:grow, pref", "fill:p:grow"))
|
||||
.add(JScrollPane(leftList).apply {
|
||||
border = BorderFactory.createMatteBorder(0, 0, 0, 1, DynamicColor.BorderColor)
|
||||
}).xy(1, 1)
|
||||
.add(box).xy(2, 1)
|
||||
.add(JScrollPane(rightList).apply {
|
||||
border = BorderFactory.createMatteBorder(0, 1, 0, 1, DynamicColor.BorderColor)
|
||||
}).xy(3, 1)
|
||||
.add(box2).xy(4, 1)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
rightList.addListSelectionListener { resetMoveButtons() }
|
||||
|
||||
leftList.addListSelectionListener {
|
||||
val indices = leftList.selectedIndices
|
||||
rightBtn.isEnabled = indices.isNotEmpty()
|
||||
}
|
||||
|
||||
leftList.model.addListDataListener(object : ListDataListener {
|
||||
override fun intervalAdded(e: ListDataEvent) {
|
||||
contentsChanged(e)
|
||||
}
|
||||
|
||||
override fun intervalRemoved(e: ListDataEvent) {
|
||||
contentsChanged(e)
|
||||
}
|
||||
|
||||
override fun contentsChanged(e: ListDataEvent) {
|
||||
allToLeftBtn.isEnabled = !rightList.model.isEmpty
|
||||
allToRightBtn.isEnabled = !leftList.model.isEmpty
|
||||
resetMoveButtons()
|
||||
}
|
||||
})
|
||||
|
||||
rightList.model.addListDataListener(object : ListDataListener {
|
||||
override fun intervalAdded(e: ListDataEvent) {
|
||||
contentsChanged(e)
|
||||
}
|
||||
|
||||
override fun intervalRemoved(e: ListDataEvent) {
|
||||
contentsChanged(e)
|
||||
}
|
||||
|
||||
override fun contentsChanged(e: ListDataEvent) {
|
||||
allToLeftBtn.isEnabled = !rightList.model.isEmpty
|
||||
allToRightBtn.isEnabled = !leftList.model.isEmpty
|
||||
resetMoveButtons()
|
||||
}
|
||||
})
|
||||
|
||||
// move first
|
||||
moveTopBtn.addActionListener {
|
||||
val indices = rightList.selectedIndices
|
||||
rightList.clearSelection()
|
||||
for (index in indices.indices) {
|
||||
val ele = rightList.model.getElementAt(indices[index])
|
||||
rightList.model.removeElementAt(indices[index])
|
||||
rightList.model.add(index, ele)
|
||||
rightList.selectionModel.addSelectionInterval(index, max(index - 1, 0))
|
||||
}
|
||||
}
|
||||
|
||||
// move up
|
||||
upBtn.addActionListener {
|
||||
val indices = rightList.selectedIndices
|
||||
rightList.clearSelection()
|
||||
for (index in indices) {
|
||||
val ele = rightList.model.getElementAt(index)
|
||||
rightList.model.removeElementAt(index)
|
||||
rightList.model.add(index - 1, ele)
|
||||
rightList.selectionModel.addSelectionInterval(max(index - 1, 0), max(index - 1, 0))
|
||||
}
|
||||
}
|
||||
|
||||
// move down
|
||||
downBtn.addActionListener {
|
||||
val indices = rightList.selectedIndices
|
||||
rightList.clearSelection()
|
||||
for (index in indices) {
|
||||
val ele = rightList.model.getElementAt(index)
|
||||
rightList.model.removeElementAt(index)
|
||||
rightList.model.add(index + 1, ele)
|
||||
rightList.selectionModel.addSelectionInterval(index + 1, index + 1)
|
||||
}
|
||||
}
|
||||
|
||||
// move last
|
||||
moveBottomBtn.addActionListener {
|
||||
val indices = rightList.selectedIndices
|
||||
val size = rightList.model.size
|
||||
rightList.clearSelection()
|
||||
for (index in indices.indices) {
|
||||
val ele = rightList.model.getElementAt(indices[index])
|
||||
rightList.model.removeElementAt(indices[index])
|
||||
rightList.model.add(size - index - 1, ele)
|
||||
rightList.selectionModel.addSelectionInterval(size - index - 1, size - index - 1)
|
||||
}
|
||||
}
|
||||
|
||||
allToLeftBtn.addActionListener {
|
||||
while (!rightList.model.isEmpty) {
|
||||
val ele = rightList.model.getElementAt(0)
|
||||
rightList.model.removeElementAt(0)
|
||||
leftList.model.addElement(ele)
|
||||
}
|
||||
}
|
||||
|
||||
allToRightBtn.addActionListener {
|
||||
while (!leftList.model.isEmpty) {
|
||||
val ele = leftList.model.getElementAt(0)
|
||||
leftList.model.removeElementAt(0)
|
||||
rightList.model.addElement(ele)
|
||||
}
|
||||
}
|
||||
|
||||
leftBtn.addActionListener {
|
||||
val indices = rightList.selectedIndices
|
||||
for (index in indices) {
|
||||
val ele = rightList.model.getElementAt(index)
|
||||
rightList.model.removeElementAt(index)
|
||||
leftList.model.addElement(ele)
|
||||
}
|
||||
rightList.clearSelection()
|
||||
val index = min(indices.max(), rightList.model.size - 1)
|
||||
if (!rightList.model.isEmpty) {
|
||||
rightList.addSelectionInterval(index, index)
|
||||
}
|
||||
}
|
||||
|
||||
rightBtn.addActionListener {
|
||||
val indices = leftList.selectedIndices
|
||||
val rightSelectedIndex = if (rightList.selectedIndices.isEmpty()) rightList.model.size else
|
||||
rightList.selectionModel.maxSelectionIndex + 1
|
||||
|
||||
if (indices.isNotEmpty()) {
|
||||
for (index in indices.indices) {
|
||||
val ele = leftList.model.getElementAt(indices[index])
|
||||
leftList.model.removeElementAt(indices[index])
|
||||
rightList.model.add(rightSelectedIndex + index, ele)
|
||||
}
|
||||
|
||||
leftList.clearSelection()
|
||||
val index = min(indices.max(), leftList.model.size - 1)
|
||||
if (!leftList.model.isEmpty) {
|
||||
leftList.addSelectionInterval(index, index)
|
||||
}
|
||||
|
||||
rightList.clearSelection()
|
||||
rightList.addSelectionInterval(rightSelectedIndex, rightSelectedIndex)
|
||||
}
|
||||
}
|
||||
|
||||
addWindowListener(object : WindowAdapter() {
|
||||
override fun windowOpened(e: WindowEvent) {
|
||||
removeWindowListener(this)
|
||||
|
||||
val allActions = toolbar.getAllActions().toMutableList()
|
||||
val shownActions = toolbar.getShownActions()
|
||||
allActions.removeAll(shownActions)
|
||||
for (action in allActions) {
|
||||
actionManager.getAction(action)?.let { leftList.model.addElement(ActionHolder(action, it)) }
|
||||
}
|
||||
for (action in shownActions) {
|
||||
actionManager.getAction(action)?.let { rightList.model.addElement(ActionHolder(action, it)) }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun resetMoveButtons() {
|
||||
val indices = rightList.selectedIndices
|
||||
if (indices.isEmpty()) {
|
||||
moveTopBtn.isEnabled = false
|
||||
moveBottomBtn.isEnabled = false
|
||||
downBtn.isEnabled = false
|
||||
upBtn.isEnabled = false
|
||||
} else {
|
||||
moveTopBtn.isEnabled = !indices.contains(0)
|
||||
upBtn.isEnabled = moveTopBtn.isEnabled
|
||||
moveBottomBtn.isEnabled = !indices.contains(rightList.model.size - 1)
|
||||
downBtn.isEnabled = moveBottomBtn.isEnabled
|
||||
}
|
||||
leftBtn.isEnabled = indices.isNotEmpty()
|
||||
}
|
||||
|
||||
private class ToolBarActionList : JList<ActionHolder>() {
|
||||
private val model = DefaultListModel<ActionHolder>()
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvents()
|
||||
setModel(model)
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
border = BorderFactory.createEmptyBorder(4, 4, 4, 4)
|
||||
background = UIManager.getColor("window")
|
||||
fixedCellHeight = UIManager.getInt("Tree.rowHeight")
|
||||
cellRenderer = object : DefaultListCellRenderer() {
|
||||
override fun getListCellRendererComponent(
|
||||
list: JList<*>?,
|
||||
value: Any?,
|
||||
index: Int,
|
||||
isSelected: Boolean,
|
||||
cellHasFocus: Boolean
|
||||
): Component {
|
||||
var text = value?.toString() ?: StringUtils.EMPTY
|
||||
if (value is ActionHolder) {
|
||||
val action = value.action
|
||||
text = action.getValue(Action.NAME)?.toString() ?: text
|
||||
}
|
||||
|
||||
val c = super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus)
|
||||
if (value is ActionHolder) {
|
||||
val action = value.action
|
||||
val icon = action.getValue(Action.SMALL_ICON) as Icon?
|
||||
if (icon != null) {
|
||||
this.icon = icon
|
||||
if (icon is DynamicIcon) {
|
||||
if (isSelected && cellHasFocus) {
|
||||
this.icon = icon.dark
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
}
|
||||
|
||||
override fun getModel(): DefaultListModel<ActionHolder> {
|
||||
return model
|
||||
}
|
||||
}
|
||||
|
||||
override fun doOKAction() {
|
||||
isOk = true
|
||||
val actions = mutableListOf<String>()
|
||||
for (i in 0 until rightList.model.size()) {
|
||||
actions.add(rightList.model.getElementAt(i).id)
|
||||
}
|
||||
Database.instance.properties.putString("Termora.ToolBar.Actions", ohMyJson.encodeToString(actions))
|
||||
super.doOKAction()
|
||||
}
|
||||
|
||||
fun open(): Boolean {
|
||||
isModal = true
|
||||
isVisible = true
|
||||
return isOk
|
||||
}
|
||||
|
||||
private class ActionHolder(val id: String, val action: Action)
|
||||
}
|
||||
@@ -3,7 +3,9 @@ package app.termora
|
||||
object Icons {
|
||||
val bulletList by lazy { DynamicIcon("icons/bulletList.svg", "icons/bulletList_dark.svg") }
|
||||
val up by lazy { DynamicIcon("icons/up.svg", "icons/up_dark.svg") }
|
||||
val moveUp by lazy { DynamicIcon("icons/moveUp.svg", "icons/moveUp_dark.svg") }
|
||||
val down by lazy { DynamicIcon("icons/down.svg", "icons/down_dark.svg") }
|
||||
val moveDown by lazy { DynamicIcon("icons/moveDown.svg", "icons/moveDown_dark.svg") }
|
||||
val close by lazy { DynamicIcon("icons/close.svg", "icons/close_dark.svg") }
|
||||
val searchHistory by lazy { DynamicIcon("icons/searchHistory.svg", "icons/searchHistory_dark.svg") }
|
||||
val matchCase by lazy { DynamicIcon("icons/matchCase.svg", "icons/matchCase_dark.svg") }
|
||||
@@ -74,9 +76,23 @@ object Icons {
|
||||
val colorPicker by lazy { DynamicIcon("icons/colorPicker.svg", "icons/colorPicker_dark.svg") }
|
||||
val folder by lazy { DynamicIcon("icons/folder.svg", "icons/folder_dark.svg") }
|
||||
val listFiles by lazy { DynamicIcon("icons/listFiles.svg", "icons/listFiles_dark.svg") }
|
||||
val left by lazy { DynamicIcon("icons/left.svg", "icons/left_dark.svg") }
|
||||
val right by lazy { DynamicIcon("icons/right.svg", "icons/right_dark.svg") }
|
||||
val dotListFiles by lazy { DynamicIcon("icons/dotListFiles.svg", "icons/dotListFiles_dark.svg") }
|
||||
val fileTransfer by lazy { DynamicIcon("icons/fileTransfer.svg", "icons/fileTransfer_dark.svg") }
|
||||
val help by lazy { DynamicIcon("icons/help.svg", "icons/help_dark.svg") }
|
||||
val applyNotConflictsLeft by lazy {
|
||||
DynamicIcon(
|
||||
"icons/applyNotConflictsLeft.svg",
|
||||
"icons/applyNotConflictsLeft_dark.svg"
|
||||
)
|
||||
}
|
||||
val applyNotConflictsRight by lazy {
|
||||
DynamicIcon(
|
||||
"icons/applyNotConflictsRight.svg",
|
||||
"icons/applyNotConflictsRight_dark.svg"
|
||||
)
|
||||
}
|
||||
val expand by lazy { DynamicIcon("icons/expand.svg", "icons/expand_dark.svg") }
|
||||
val collapse by lazy { DynamicIcon("icons/collapse.svg", "icons/collapse_dark.svg") }
|
||||
val expandAll by lazy { DynamicIcon("icons/expandAll.svg", "icons/expandAll_dark.svg") }
|
||||
|
||||
@@ -7,27 +7,21 @@ import app.termora.findeverywhere.FindEverywhereResult
|
||||
import com.formdev.flatlaf.FlatLaf
|
||||
import com.formdev.flatlaf.extras.components.FlatPopupMenu
|
||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import org.jdesktop.swingx.action.ActionContainerFactory
|
||||
import org.jdesktop.swingx.action.ActionManager
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Component
|
||||
import java.awt.Dimension
|
||||
import java.awt.event.ActionEvent
|
||||
import java.awt.event.KeyEvent
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import java.beans.PropertyChangeEvent
|
||||
import java.awt.*
|
||||
import java.awt.event.*
|
||||
import java.beans.PropertyChangeListener
|
||||
import javax.swing.*
|
||||
import javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT
|
||||
import kotlin.math.min
|
||||
|
||||
class TerminalTabbed(
|
||||
private val toolbar: JToolBar,
|
||||
private val termoraToolBar: TermoraToolBar,
|
||||
private val tabbedPane: FlatTabbedPane,
|
||||
) : JPanel(BorderLayout()), Disposable, TerminalTabbedManager {
|
||||
private val tabs = mutableListOf<TerminalTab>()
|
||||
private val customizeToolBarAWTEventListener = CustomizeToolBarAWTEventListener()
|
||||
private val toolbar = termoraToolBar.getJToolBar()
|
||||
|
||||
private val iconListener = PropertyChangeListener { e ->
|
||||
val source = e.source
|
||||
@@ -53,34 +47,6 @@ class TerminalTabbed(
|
||||
tabbedPane.styleMap = mapOf(
|
||||
"focusColor" to UIManager.getColor("TabbedPane.selectedBackground")
|
||||
)
|
||||
|
||||
val actionManager = ActionManager.getInstance()
|
||||
val actionContainerFactory = ActionContainerFactory(actionManager)
|
||||
val updateBtn = actionContainerFactory.createButton(actionManager.getAction(Actions.APP_UPDATE))
|
||||
updateBtn.isVisible = updateBtn.isEnabled
|
||||
updateBtn.addChangeListener { updateBtn.isVisible = updateBtn.isEnabled }
|
||||
|
||||
toolbar.add(actionContainerFactory.createButton(object : AnAction(StringUtils.EMPTY, Icons.add) {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
actionManager.getAction(Actions.FIND_EVERYWHERE)?.actionPerformed(e)
|
||||
}
|
||||
|
||||
override fun isEnabled(): Boolean {
|
||||
return actionManager.getAction(Actions.FIND_EVERYWHERE)?.isEnabled ?: false
|
||||
}
|
||||
}))
|
||||
toolbar.add(Box.createHorizontalStrut(UIManager.getInt("TabbedPane.tabHeight")))
|
||||
toolbar.add(Box.createHorizontalGlue())
|
||||
toolbar.add(actionContainerFactory.createButton(actionManager.getAction(Actions.TERMINAL_LOGGER)))
|
||||
toolbar.add(actionContainerFactory.createButton(actionManager.getAction(Actions.MACRO)))
|
||||
toolbar.add(actionContainerFactory.createButton(actionManager.getAction(Actions.KEYWORD_HIGHLIGHT_EVERYWHERE)))
|
||||
toolbar.add(actionContainerFactory.createButton(actionManager.getAction(Actions.KEY_MANAGER)))
|
||||
toolbar.add(actionContainerFactory.createButton(actionManager.getAction(Actions.MULTIPLE)))
|
||||
toolbar.add(updateBtn)
|
||||
toolbar.add(actionContainerFactory.createButton(actionManager.getAction(Actions.FIND_EVERYWHERE)))
|
||||
toolbar.add(actionContainerFactory.createButton(actionManager.getAction(Actions.SETTING)))
|
||||
|
||||
|
||||
tabbedPane.trailingComponent = toolbar
|
||||
|
||||
add(tabbedPane, BorderLayout.CENTER)
|
||||
@@ -93,18 +59,16 @@ class TerminalTabbed(
|
||||
tabbedPane.setTabCloseCallback { _, i -> removeTabAt(i, true) }
|
||||
|
||||
// 选中变动
|
||||
tabbedPane.addPropertyChangeListener("selectedIndex", object : PropertyChangeListener {
|
||||
override fun propertyChange(evt: PropertyChangeEvent) {
|
||||
val oldIndex = evt.oldValue as Int
|
||||
val newIndex = evt.newValue as Int
|
||||
if (oldIndex >= 0 && tabs.size > newIndex) {
|
||||
tabs[oldIndex].onLostFocus()
|
||||
}
|
||||
if (newIndex >= 0 && tabs.size > newIndex) {
|
||||
tabs[newIndex].onGrabFocus()
|
||||
}
|
||||
tabbedPane.addPropertyChangeListener("selectedIndex") { evt ->
|
||||
val oldIndex = evt.oldValue as Int
|
||||
val newIndex = evt.newValue as Int
|
||||
if (oldIndex >= 0 && tabs.size > newIndex) {
|
||||
tabs[oldIndex].onLostFocus()
|
||||
}
|
||||
})
|
||||
if (newIndex >= 0 && tabs.size > newIndex) {
|
||||
tabs[newIndex].onGrabFocus()
|
||||
}
|
||||
}
|
||||
|
||||
// 选择变动
|
||||
tabbedPane.addChangeListener {
|
||||
@@ -209,6 +173,9 @@ class TerminalTabbed(
|
||||
}
|
||||
})
|
||||
|
||||
// 监听全局事件
|
||||
toolkit.addAWTEventListener(customizeToolBarAWTEventListener, AWTEvent.MOUSE_EVENT_MASK)
|
||||
|
||||
}
|
||||
|
||||
private fun removeTabAt(index: Int, disposable: Boolean = true) {
|
||||
@@ -274,14 +241,10 @@ class TerminalTabbed(
|
||||
// 克隆
|
||||
val clone = popupMenu.add(I18n.getString("termora.tabbed.contextmenu.clone"))
|
||||
clone.addActionListener {
|
||||
val index = tabbedPane.selectedIndex
|
||||
if (index > 0) {
|
||||
val tab = tabs[index]
|
||||
if (tab is HostTerminalTab) {
|
||||
ActionManager.getInstance()
|
||||
.getAction(Actions.OPEN_HOST)
|
||||
.actionPerformed(OpenHostActionEvent(this, tab.host))
|
||||
}
|
||||
if (tab is HostTerminalTab) {
|
||||
ActionManager.getInstance()
|
||||
.getAction(Actions.OPEN_HOST)
|
||||
.actionPerformed(OpenHostActionEvent(this, tab.host))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,6 +333,64 @@ class TerminalTabbed(
|
||||
Disposer.register(this, tab)
|
||||
}
|
||||
|
||||
/**
|
||||
* 对着 ToolBar 右键
|
||||
*/
|
||||
private inner class CustomizeToolBarAWTEventListener : AWTEventListener, Disposable {
|
||||
init {
|
||||
Disposer.register(this@TerminalTabbed, this)
|
||||
}
|
||||
|
||||
override fun eventDispatched(event: AWTEvent) {
|
||||
if (event !is MouseEvent || event.id != MouseEvent.MOUSE_CLICKED || !SwingUtilities.isRightMouseButton(event)) return
|
||||
// 如果 ToolBar 没有显示
|
||||
if (!toolbar.isShowing) return
|
||||
// 如果不是作用于在 ToolBar 上面
|
||||
if (!Rectangle(toolbar.locationOnScreen, toolbar.size).contains(event.locationOnScreen)) return
|
||||
|
||||
// 显示右键菜单
|
||||
showContextMenu(event)
|
||||
}
|
||||
|
||||
private fun showContextMenu(event: MouseEvent) {
|
||||
val popupMenu = FlatPopupMenu()
|
||||
popupMenu.add(I18n.getString("termora.toolbar.customize-toolbar")).addActionListener {
|
||||
val dialog = CustomizeToolBarDialog(
|
||||
SwingUtilities.getWindowAncestor(this@TerminalTabbed),
|
||||
termoraToolBar
|
||||
)
|
||||
if (dialog.open()) {
|
||||
termoraToolBar.rebuild()
|
||||
}
|
||||
}
|
||||
popupMenu.show(event.component, event.x, event.y)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
toolkit.removeAWTEventListener(this)
|
||||
}
|
||||
}
|
||||
|
||||
/*private inner class CustomizeToolBarDialog(owner: Window) : DialogWrapper(owner) {
|
||||
init {
|
||||
size = Dimension(UIManager.getInt("Dialog.width"), UIManager.getInt("Dialog.height"))
|
||||
isModal = true
|
||||
title = I18n.getString("termora.setting")
|
||||
setLocationRelativeTo(null)
|
||||
|
||||
init()
|
||||
}
|
||||
|
||||
override fun createCenterPanel(): JComponent {
|
||||
val model = DefaultListModel<String>()
|
||||
val checkBoxList = CheckBoxList(model)
|
||||
checkBoxList.fixedCellHeight = UIManager.getInt("Tree.rowHeight")
|
||||
model.addElement("Test")
|
||||
return checkBoxList
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
private inner class SwitchFindEverywhereResult(
|
||||
private val title: String,
|
||||
private val icon: Icon?,
|
||||
|
||||
@@ -44,12 +44,12 @@ class TermoraFrame : JFrame() {
|
||||
private val log = LoggerFactory.getLogger(TermoraFrame::class.java)
|
||||
}
|
||||
|
||||
private val toolbar = JToolBar()
|
||||
private val titleBar = LogicCustomTitleBar.createCustomTitleBar(this)
|
||||
private val tabbedPane = MyTabbedPane()
|
||||
private val toolbar = TermoraToolBar(titleBar, tabbedPane)
|
||||
private lateinit var terminalTabbed: TerminalTabbed
|
||||
private val disposable = Disposer.newDisposable()
|
||||
private val isWindowDecorationsSupported by lazy { JBR.isWindowDecorationsSupported() }
|
||||
private val titleBar = LogicCustomTitleBar.createCustomTitleBar(this)
|
||||
private val updaterManager get() = UpdaterManager.instance
|
||||
|
||||
private val preferencesHandler = object : Runnable {
|
||||
@@ -81,38 +81,6 @@ class TermoraFrame : JFrame() {
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
// 监听窗口大小变动,然后修改边距避开控制按钮
|
||||
addComponentListener(object : ComponentAdapter() {
|
||||
override fun componentResized(e: ComponentEvent) {
|
||||
if (SystemInfo.isMacOS) {
|
||||
val left = titleBar.leftInset.toInt()
|
||||
if (tabbedPane.tabAreaInsets.left != left) {
|
||||
tabbedPane.tabAreaInsets = Insets(0, left, 0, 0)
|
||||
}
|
||||
} else if (SystemInfo.isWindows || SystemInfo.isLinux) {
|
||||
|
||||
val right = titleBar.rightInset.toInt()
|
||||
|
||||
for (i in 0 until toolbar.componentCount) {
|
||||
val c = toolbar.getComponent(i)
|
||||
if (c.name == "spacing") {
|
||||
if (c.width == right) {
|
||||
return
|
||||
}
|
||||
toolbar.remove(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (right > 0) {
|
||||
val spacing = Box.createHorizontalStrut(right)
|
||||
spacing.name = "spacing"
|
||||
toolbar.add(spacing)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
forceHitTest()
|
||||
|
||||
// macos 需要判断是否全部删除
|
||||
@@ -210,7 +178,7 @@ class TermoraFrame : JFrame() {
|
||||
|
||||
|
||||
// Keyword Highlight
|
||||
ActionManager.getInstance().addAction(Actions.KEYWORD_HIGHLIGHT_EVERYWHERE, object : AnAction(
|
||||
ActionManager.getInstance().addAction(Actions.KEYWORD_HIGHLIGHT, object : AnAction(
|
||||
I18n.getString("termora.highlight"),
|
||||
Icons.edit
|
||||
) {
|
||||
@@ -444,8 +412,8 @@ class TermoraFrame : JFrame() {
|
||||
tabbedPane.addMouseListener(mouseAdapter)
|
||||
tabbedPane.addMouseMotionListener(mouseAdapter)
|
||||
|
||||
toolbar.addMouseListener(mouseAdapter)
|
||||
toolbar.addMouseMotionListener(mouseAdapter)
|
||||
toolbar.getJToolBar().addMouseListener(mouseAdapter)
|
||||
toolbar.getJToolBar().addMouseMotionListener(mouseAdapter)
|
||||
}
|
||||
|
||||
private fun initDesktopHandler() {
|
||||
|
||||
141
src/main/kotlin/app/termora/TermoraToolBar.kt
Normal file
@@ -0,0 +1,141 @@
|
||||
package app.termora
|
||||
|
||||
import app.termora.Application.ohMyJson
|
||||
import app.termora.db.Database
|
||||
import com.formdev.flatlaf.extras.components.FlatTabbedPane
|
||||
import com.formdev.flatlaf.util.SystemInfo
|
||||
import com.jetbrains.WindowDecorations
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import org.jdesktop.swingx.action.ActionContainerFactory
|
||||
import org.jdesktop.swingx.action.ActionManager
|
||||
import java.awt.Insets
|
||||
import java.awt.event.ActionEvent
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import javax.swing.Box
|
||||
import javax.swing.JToolBar
|
||||
|
||||
class TermoraToolBar(
|
||||
private val titleBar: WindowDecorations.CustomTitleBar,
|
||||
private val tabbedPane: FlatTabbedPane
|
||||
) {
|
||||
private val properties by lazy { Database.instance.properties }
|
||||
private val toolbar by lazy { MyToolBar().apply { rebuild(this) } }
|
||||
|
||||
private val shownActions = mutableListOf<String>()
|
||||
|
||||
fun getJToolBar(): JToolBar {
|
||||
return toolbar
|
||||
}
|
||||
|
||||
|
||||
fun getShownActions(): List<String> {
|
||||
return shownActions
|
||||
}
|
||||
|
||||
fun getAllActions(): List<String> {
|
||||
return listOf(
|
||||
Actions.TERMINAL_LOGGER,
|
||||
Actions.MACRO,
|
||||
Actions.KEYWORD_HIGHLIGHT,
|
||||
Actions.KEY_MANAGER,
|
||||
Actions.MULTIPLE,
|
||||
Actions.FIND_EVERYWHERE,
|
||||
Actions.SETTING,
|
||||
)
|
||||
}
|
||||
|
||||
fun rebuild() {
|
||||
rebuild(this.toolbar)
|
||||
}
|
||||
|
||||
private fun rebuild(toolbar: JToolBar) {
|
||||
val actionManager = ActionManager.getInstance()
|
||||
val actionContainerFactory = ActionContainerFactory(actionManager)
|
||||
|
||||
shownActions.clear()
|
||||
toolbar.removeAll()
|
||||
|
||||
toolbar.add(actionContainerFactory.createButton(object : AnAction(StringUtils.EMPTY, Icons.add) {
|
||||
override fun actionPerformed(e: ActionEvent?) {
|
||||
actionManager.getAction(Actions.FIND_EVERYWHERE)?.actionPerformed(e)
|
||||
}
|
||||
|
||||
override fun isEnabled(): Boolean {
|
||||
return actionManager.getAction(Actions.FIND_EVERYWHERE)?.isEnabled ?: false
|
||||
}
|
||||
}))
|
||||
|
||||
toolbar.add(Box.createHorizontalGlue())
|
||||
|
||||
val actions = ohMyJson.runCatching {
|
||||
ohMyJson.decodeFromString<List<String>>(
|
||||
properties.getString(
|
||||
"Termora.ToolBar.Actions",
|
||||
StringUtils.EMPTY
|
||||
)
|
||||
)
|
||||
}.getOrNull() ?: getAllActions()
|
||||
|
||||
|
||||
// update btn
|
||||
val updateBtn = actionContainerFactory.createButton(actionManager.getAction(Actions.APP_UPDATE))
|
||||
updateBtn.isVisible = updateBtn.isEnabled
|
||||
updateBtn.addChangeListener { updateBtn.isVisible = updateBtn.isEnabled }
|
||||
toolbar.add(updateBtn)
|
||||
|
||||
for (action in actions) {
|
||||
actionManager.getAction(action)?.let {
|
||||
toolbar.add(actionContainerFactory.createButton(it))
|
||||
shownActions.add(action)
|
||||
}
|
||||
}
|
||||
|
||||
if (toolbar is MyToolBar) {
|
||||
toolbar.adjust()
|
||||
}
|
||||
|
||||
toolbar.revalidate()
|
||||
toolbar.repaint()
|
||||
}
|
||||
|
||||
private inner class MyToolBar : JToolBar() {
|
||||
init {
|
||||
// 监听窗口大小变动,然后修改边距避开控制按钮
|
||||
addComponentListener(object : ComponentAdapter() {
|
||||
override fun componentResized(e: ComponentEvent) {
|
||||
adjust()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun adjust() {
|
||||
if (SystemInfo.isMacOS) {
|
||||
val left = titleBar.leftInset.toInt()
|
||||
if (tabbedPane.tabAreaInsets.left != left) {
|
||||
tabbedPane.tabAreaInsets = Insets(0, left, 0, 0)
|
||||
}
|
||||
} else if (SystemInfo.isWindows || SystemInfo.isLinux) {
|
||||
|
||||
val right = titleBar.rightInset.toInt()
|
||||
val toolbar = this@MyToolBar
|
||||
for (i in 0 until toolbar.componentCount) {
|
||||
val c = toolbar.getComponent(i)
|
||||
if (c.name == "spacing") {
|
||||
if (c.width == right) {
|
||||
return
|
||||
}
|
||||
toolbar.remove(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (right > 0) {
|
||||
val spacing = Box.createHorizontalStrut(right)
|
||||
spacing.name = "spacing"
|
||||
toolbar.add(spacing)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,12 @@ import app.termora.I18n
|
||||
import org.jdesktop.swingx.action.ActionManager
|
||||
|
||||
class QuickActionsFindEverywhereProvider : FindEverywhereProvider {
|
||||
private val actions = listOf(Actions.KEY_MANAGER, Actions.KEYWORD_HIGHLIGHT_EVERYWHERE, Actions.MULTIPLE)
|
||||
private val actions = listOf(
|
||||
Actions.KEY_MANAGER,
|
||||
Actions.KEYWORD_HIGHLIGHT,
|
||||
Actions.MULTIPLE,
|
||||
)
|
||||
|
||||
override fun find(pattern: String): List<FindEverywhereResult> {
|
||||
val actionManager = ActionManager.getInstance()
|
||||
return actions
|
||||
|
||||
@@ -268,7 +268,8 @@ termora.transport.jobs.table.estimated-time=Estimated time
|
||||
|
||||
termora.transport.jobs.contextmenu.delete=${termora.remove}
|
||||
termora.transport.jobs.contextmenu.delete-all=Delete All
|
||||
|
||||
# ToolBar
|
||||
termora.toolbar.customize-toolbar=Customize Toolbar...
|
||||
|
||||
# Terminal
|
||||
termora.terminal.size=Size: {0} x {1}
|
||||
|
||||
@@ -260,6 +260,8 @@ termora.transport.jobs.table.speed=速度
|
||||
termora.transport.jobs.table.estimated-time=剩余时间
|
||||
|
||||
termora.transport.jobs.contextmenu.delete-all=删除所有
|
||||
# ToolBar
|
||||
termora.toolbar.customize-toolbar=自定义工具栏...
|
||||
|
||||
termora.terminal.size=大小: {0} x {1}
|
||||
termora.terminal.copied=已复制
|
||||
|
||||
@@ -240,6 +240,8 @@ termora.transport.jobs.table.speed=速度
|
||||
termora.transport.jobs.table.estimated-time=剩餘時間
|
||||
|
||||
termora.transport.jobs.contextmenu.delete-all=刪除所有
|
||||
# ToolBar
|
||||
termora.toolbar.customize-toolbar=自訂工具列...
|
||||
|
||||
termora.terminal.size=大小: {0} x {1}
|
||||
termora.terminal.copied=已複製
|
||||
|
||||
4
src/main/resources/icons/applyNotConflictsLeft.svg
Normal 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="M8.5 12.5L13 8L8.5 3.5M3.5 12.5L8 8L3.5 3.5" stroke="#6C707E" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 330 B |
4
src/main/resources/icons/applyNotConflictsLeft_dark.svg
Normal 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="M8.5 12.5L13 8L8.5 3.5M3.5 12.5L8 8L3.5 3.5" stroke="#CED0D6" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 330 B |
4
src/main/resources/icons/applyNotConflictsRight.svg
Normal 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="M7.5 3.5L3 8L7.5 12.5M12.5 3.5L8 8L12.5 12.5" stroke="#6C707E" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 331 B |
4
src/main/resources/icons/applyNotConflictsRight_dark.svg
Normal 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="M7.5 3.5L3 8L7.5 12.5M12.5 3.5L8 8L12.5 12.5" stroke="#CED0D6" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 331 B |
6
src/main/resources/icons/left.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- 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 fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M6.3464 3.64645C6.54166 3.45118 6.85824 3.45118 7.0535 3.64645C7.24877 3.84171 7.24877 4.15829 7.0535 4.35355L3.90352 7.50354L13.5035 7.50354C13.7797 7.50354 14.0035 7.7274 14.0035 8.00354C14.0035 8.27968 13.7797 8.50354 13.5035 8.50354L3.91059 8.50354L7.05351 11.6464C7.24877 11.8417 7.24877 12.1583 7.05351 12.3536C6.85824 12.5488 6.54166 12.5488 6.3464 12.3536L2.3464 8.35355L1.99284 8L2.3464 7.64645L6.3464 3.64645Z"
|
||||
fill="#6C707E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 741 B |
6
src/main/resources/icons/left_dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- 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 fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M6.3464 3.64645C6.54166 3.45118 6.85824 3.45118 7.0535 3.64645C7.24877 3.84171 7.24877 4.15829 7.0535 4.35355L3.90352 7.50354L13.5035 7.50354C13.7797 7.50354 14.0035 7.7274 14.0035 8.00354C14.0035 8.27968 13.7797 8.50354 13.5035 8.50354L3.91059 8.50354L7.05351 11.6464C7.24877 11.8417 7.24877 12.1583 7.05351 12.3536C6.85824 12.5488 6.54166 12.5488 6.3464 12.3536L2.3464 8.35355L1.99284 8L2.3464 7.64645L6.3464 3.64645Z"
|
||||
fill="#CED0D6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 741 B |
8
src/main/resources/icons/moveDown.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- 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 fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M11.8536 10.1535C12.0488 9.95828 12.0488 9.6417 11.8536 9.44644C11.6583 9.25117 11.3417 9.25117 11.1464 9.44644L8.5 12.0929L8.5 4.5C8.5 4.22386 8.27615 4 8 4C7.72386 4 7.5 4.22386 7.5 4.5L7.5 12.0929L4.85355 9.44644C4.65829 9.25118 4.34171 9.25118 4.14645 9.44644C3.95118 9.6417 3.95118 9.95828 4.14645 10.1535L7.64645 13.6535L8 14.0071L8.35355 13.6535L11.8536 10.1535Z"
|
||||
fill="#6C707E"/>
|
||||
|
||||
<rect x="2" y="15" width="12" height="1" rx="0.5" fill="#6C707E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 763 B |
8
src/main/resources/icons/moveDown_dark.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- 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 fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M11.8536 10.1535C12.0488 9.95828 12.0488 9.6417 11.8536 9.44644C11.6583 9.25117 11.3417 9.25117 11.1464 9.44644L8.5 12.0929L8.5 4.5C8.5 4.22386 8.27615 4 8 4C7.72386 4 7.5 4.22386 7.5 4.5L7.5 12.0929L4.85355 9.44644C4.65829 9.25118 4.34171 9.25118 4.14645 9.44644C3.95118 9.6417 3.95118 9.95828 4.14645 10.1535L7.64645 13.6535L8 14.0071L8.35355 13.6535L11.8536 10.1535Z"
|
||||
fill="#CED0D6"/>
|
||||
|
||||
<rect x="2" y="15" width="12" height="1" rx="0.5" fill="#CED0D6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 763 B |
7
src/main/resources/icons/moveUp.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!-- 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">
|
||||
<rect x="2" y="0" width="12" height="1" rx="0.5" fill="#6C707E"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M11.8536 5.85354C12.0488 6.0488 12.0488 6.36538 11.8536 6.56064C11.6583 6.75591 11.3417 6.75591 11.1464 6.56064L8.5 3.9142L8.5 11.5071C8.5 11.7832 8.27615 12.0071 8 12.0071C7.72386 12.0071 7.5 11.7832 7.5 11.5071L7.5 3.91419L4.85355 6.56064C4.65829 6.7559 4.34171 6.7559 4.14645 6.56064C3.95118 6.36538 3.95118 6.0488 4.14645 5.85353L7.64645 2.35354L8 1.99998L8.35355 2.35354L11.8536 5.85354Z"
|
||||
fill="#6C707E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 783 B |
7
src/main/resources/icons/moveUp_dark.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!-- 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">
|
||||
<rect x="2" y="0" width="12" height="1" rx="0.5" fill="#CED0D6"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M11.8536 5.85354C12.0488 6.0488 12.0488 6.36538 11.8536 6.56064C11.6583 6.75591 11.3417 6.75591 11.1464 6.56064L8.5 3.9142L8.5 11.5071C8.5 11.7832 8.27615 12.0071 8 12.0071C7.72386 12.0071 7.5 11.7832 7.5 11.5071L7.5 3.91419L4.85355 6.56064C4.65829 6.7559 4.34171 6.7559 4.14645 6.56064C3.95118 6.36538 3.95118 6.0488 4.14645 5.85353L7.64645 2.35354L8 1.99998L8.35355 2.35354L11.8536 5.85354Z"
|
||||
fill="#CED0D6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 783 B |
6
src/main/resources/icons/right.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- 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 fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M9.65355 12.3536C9.45829 12.5488 9.14171 12.5488 8.94645 12.3536C8.75118 12.1583 8.75118 11.8417 8.94645 11.6464L12.0894 8.50354L2.49646 8.50354C2.22032 8.50354 1.99646 8.27968 1.99646 8.00354C1.99646 7.7274 2.22032 7.50354 2.49646 7.50354L12.0964 7.50354L8.94645 4.35355C8.75118 4.15829 8.75118 3.84171 8.94645 3.64645C9.14171 3.45118 9.45829 3.45118 9.65355 3.64645L13.6536 7.64645L14.0071 8L13.6536 8.35355L9.65355 12.3536Z"
|
||||
fill="#6C707E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 748 B |
6
src/main/resources/icons/right_dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- 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 fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M9.65355 12.3536C9.45829 12.5488 9.14171 12.5488 8.94645 12.3536C8.75118 12.1583 8.75118 11.8417 8.94645 11.6464L12.0894 8.50354L2.49646 8.50354C2.22032 8.50354 1.99646 8.27968 1.99646 8.00354C1.99646 7.7274 2.22032 7.50354 2.49646 7.50354L12.0964 7.50354L8.94645 4.35355C8.75118 4.15829 8.75118 3.84171 8.94645 3.64645C9.14171 3.45118 9.45829 3.45118 9.65355 3.64645L13.6536 7.64645L14.0071 8L13.6536 8.35355L9.65355 12.3536Z"
|
||||
fill="#CED0D6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 748 B |