From 8988ed8b005f50eafa3c589603ad83b8d9e82508 Mon Sep 17 00:00:00 2001 From: Hannah Schellekens Date: Mon, 11 Jan 2021 13:11:18 +0100 Subject: [PATCH 1/8] Moved table wizard to action.wizard.table package --- .../wizard/table}/ColumnType.kt | 2 +- .../action/wizard/table/LatexTableWizardAction.kt | 2 -- .../wizard/table}/TableCreationDialogWrapper.kt | 3 +-- .../wizard/table}/TableCreationEditColumnDialog.kt | 10 +++++----- .../wizard/table}/TableCreationTableModel.kt | 2 +- .../texifyidea/action/wizard/table/TableInformation.kt | 3 --- 6 files changed, 8 insertions(+), 14 deletions(-) rename src/nl/hannahsten/texifyidea/{ui/tablecreationdialog => action/wizard/table}/ColumnType.kt (74%) rename src/nl/hannahsten/texifyidea/{ui/tablecreationdialog => action/wizard/table}/TableCreationDialogWrapper.kt (98%) rename src/nl/hannahsten/texifyidea/{ui/tablecreationdialog => action/wizard/table}/TableCreationEditColumnDialog.kt (89%) rename src/nl/hannahsten/texifyidea/{ui/tablecreationdialog => action/wizard/table}/TableCreationTableModel.kt (94%) diff --git a/src/nl/hannahsten/texifyidea/ui/tablecreationdialog/ColumnType.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/ColumnType.kt similarity index 74% rename from src/nl/hannahsten/texifyidea/ui/tablecreationdialog/ColumnType.kt rename to src/nl/hannahsten/texifyidea/action/wizard/table/ColumnType.kt index 377c902e3..f0d378c70 100644 --- a/src/nl/hannahsten/texifyidea/ui/tablecreationdialog/ColumnType.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/ColumnType.kt @@ -1,4 +1,4 @@ -package nl.hannahsten.texifyidea.ui.tablecreationdialog +package nl.hannahsten.texifyidea.action.wizard.table /** * @author Abby Berkers diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt index ed6d8d6ed..dce055d76 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt @@ -6,8 +6,6 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.command.WriteCommandAction import nl.hannahsten.texifyidea.action.insert.InsertTable import nl.hannahsten.texifyidea.lang.LatexPackage -import nl.hannahsten.texifyidea.ui.tablecreationdialog.ColumnType -import nl.hannahsten.texifyidea.ui.tablecreationdialog.TableCreationDialogWrapper import nl.hannahsten.texifyidea.util.caretOffset import nl.hannahsten.texifyidea.util.currentTextEditor import nl.hannahsten.texifyidea.util.files.psiFile diff --git a/src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationDialogWrapper.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt similarity index 98% rename from src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationDialogWrapper.kt rename to src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt index 070c12c0d..110079989 100644 --- a/src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationDialogWrapper.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt @@ -1,4 +1,4 @@ -package nl.hannahsten.texifyidea.ui.tablecreationdialog +package nl.hannahsten.texifyidea.action.wizard.table import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.KeyboardShortcut @@ -13,7 +13,6 @@ import com.intellij.ui.components.JBTextField import com.intellij.ui.scale.JBUIScale.scale import com.intellij.ui.table.JBTable import com.intellij.util.IconUtil -import nl.hannahsten.texifyidea.action.wizard.table.TableInformation import java.awt.* import java.awt.event.ActionEvent import java.awt.event.KeyEvent diff --git a/src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationEditColumnDialog.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt similarity index 89% rename from src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationEditColumnDialog.kt rename to src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt index a818fa509..6288d344f 100644 --- a/src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationEditColumnDialog.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt @@ -1,4 +1,4 @@ -package nl.hannahsten.texifyidea.ui.tablecreationdialog +package nl.hannahsten.texifyidea.action.wizard.table import com.intellij.openapi.ui.DialogBuilder import com.intellij.openapi.ui.DialogWrapper @@ -19,10 +19,10 @@ import javax.swing.JPanel * @author Abby Berkers */ class TableCreationEditColumnDialog( - private val onOkFunction: (String, ColumnType, Int) -> Unit, - private val editingColumn: Int, - private val columnName: String = "", - private val columnType: ColumnType = ColumnType.TEXT_COLUMN + private val onOkFunction: (String, ColumnType, Int) -> Unit, + private val editingColumn: Int, + private val columnName: String = "", + private val columnType: ColumnType = ColumnType.TEXT_COLUMN ) { init { diff --git a/src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationTableModel.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt similarity index 94% rename from src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationTableModel.kt rename to src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt index 5fbe5ac37..7e4bd8e3e 100644 --- a/src/nl/hannahsten/texifyidea/ui/tablecreationdialog/TableCreationTableModel.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt @@ -1,4 +1,4 @@ -package nl.hannahsten.texifyidea.ui.tablecreationdialog +package nl.hannahsten.texifyidea.action.wizard.table import java.util.* import javax.swing.table.DefaultTableModel diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableInformation.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableInformation.kt index 14ca6da1d..98156e156 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableInformation.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableInformation.kt @@ -1,8 +1,5 @@ package nl.hannahsten.texifyidea.action.wizard.table -import nl.hannahsten.texifyidea.ui.tablecreationdialog.ColumnType -import nl.hannahsten.texifyidea.ui.tablecreationdialog.TableCreationTableModel - /** * Stores all information about a table. * From a1822b6569177a93a79321abdc66e32ff8625955 Mon Sep 17 00:00:00 2001 From: Hannah Schellekens Date: Mon, 11 Jan 2021 14:11:19 +0100 Subject: [PATCH 2/8] Refactored table wizard. --- .../action/wizard/table/ColumnType.kt | 1 + .../wizard/table/LatexTableWizardAction.kt | 9 +- .../table/TableCreationDialogWrapper.kt | 228 +++++++++--------- .../table/TableCreationEditColumnDialog.kt | 26 +- .../wizard/table/TableCreationTableModel.kt | 2 +- .../action/wizard/table/TableInformation.kt | 23 +- 6 files changed, 162 insertions(+), 127 deletions(-) diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/ColumnType.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/ColumnType.kt index f0d378c70..0abe8179c 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/ColumnType.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/ColumnType.kt @@ -4,6 +4,7 @@ package nl.hannahsten.texifyidea.action.wizard.table * @author Abby Berkers */ enum class ColumnType(val displayName: String) { + TEXT_COLUMN("Text"), MATH_COLUMN("Math"), NUMBERS_COLUMN("Numbers") diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt index dce055d76..7b2d93113 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt @@ -32,6 +32,7 @@ class LatexTableWizardAction : AnAction() { // Create the dialog. val dialogWrapper = TableCreationDialogWrapper() + // If the user pressed OK, do stuff. if (dialogWrapper.showAndGet()) { @@ -46,7 +47,7 @@ class LatexTableWizardAction : AnAction() { project, "Insert table", "LaTeX", - Runnable { file.psiFile(project)!!.insertUsepackage(LatexPackage.BOOKTABS) }, + Runnable { file.psiFile(project)?.insertUsepackage(LatexPackage.BOOKTABS) }, file.psiFile(project) ) } @@ -56,8 +57,10 @@ class LatexTableWizardAction : AnAction() { * Convert the table information to a latex table that can be inserted into the file. * * @param tableInformation - * @param lineIndent is the indentation of the current line, to be used on each new line. - * @param tabIndent is the continuation indent. + * @param lineIndent + * The indentation of the current line, to be used on each new line. + * @param tabIndent + * The continuation indent. */ private fun convertTableToLatex(tableInformation: TableInformation, lineIndent: String, tabIndent: String = " "): String { /** diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt index 110079989..40e795f87 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt @@ -4,13 +4,12 @@ import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.KeyboardShortcut import com.intellij.openapi.actionSystem.ShortcutSet import com.intellij.openapi.ui.DialogWrapper -import com.intellij.openapi.ui.ValidationInfo import com.intellij.ui.AnActionButton import com.intellij.ui.LayeredIcon import com.intellij.ui.ToolbarDecorator import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBTextField -import com.intellij.ui.scale.JBUIScale.scale +import com.intellij.ui.scale.JBUIScale import com.intellij.ui.table.JBTable import com.intellij.util.IconUtil import java.awt.* @@ -20,30 +19,43 @@ import javax.swing.* import javax.swing.border.EmptyBorder /** - * Wrapper that contains the table creation dialog. It validates the form when clicking the OK button. - * - * @param columnTypes The types of the columns of the table, see [ColumnType], always start with an empty table. - * @param tableModel The model of the table, always start with an empty table. - * @param tableInformation Information about the table that is needed to convert it to latex. - * - * UI components that have to be validated when clicking the OK button, i.e., checking if the user entered something. - * @param table The JTable component that shows the table. - * @param caption The text field that contains the caption for the table. - * @param reference The text field that contains the label for the table. It has a default value "tab:" to encourage usage - * of label conventions. + * Wrapper that contains the table creation dialog. * * @author Abby Berkers */ -class TableCreationDialogWrapper( - private val columnTypes: MutableList = emptyList().toMutableList(), - private val tableModel: TableCreationTableModel = TableCreationTableModel(), - var tableInformation: TableInformation = TableInformation(tableModel, columnTypes, "", ""), - // Components that have to be validated when clicking the OK button. - private val table: JTable = JBTable(tableModel), - private val caption: JBTextField = JBTextField(), - private val reference: JBTextField = JBTextField("tab:") -) : - DialogWrapper(true) { +open class TableCreationDialogWrapper : DialogWrapper(true) { + + /** + * Types of the columns of the table, see [ColumnType], always start with an empty table. + */ + private val columnTypes = mutableListOf() + + /** + * The model of the table, always start with an empty table. + */ + private val tableModel = TableCreationTableModel() + + /** + * The table component that shows the table. + */ + private val table = JBTable(tableModel) + + /** + * The text field that contains the caption for the table. + */ + private val lblCaption = JBTextField() + + /** + * The text field that contains the label for the table. It has a default value "tab:" to encourage usage + * of label conventions. + */ + private val txtReference = JBTextField("tab:") + + /** + * Information about the table that is needed to convert it to latex. + */ + var tableInformation = TableInformation(tableModel, columnTypes, "", "") + private set init { // Initialise the dialog, otherwise it shows as a line (i.e., infinitely small) and without any of the elements. @@ -57,14 +69,17 @@ class TableCreationDialogWrapper( * @param title of the column. * @param columnType is the column type of the column. */ - @Suppress("KDocUnresolvedReference") - private val addColumnFun = fun(title: String, columnType: ColumnType, _: Int) { + private fun addTableColumn(title: String, columnType: ColumnType) { // Add the column to the table, with an empty cell for each row (instead of the default null). tableModel.addColumn(title, (0 until tableModel.rowCount).map { "" }.toTypedArray()) + // Add the column type to the list of column types. columnTypes.add(columnType) + // If table is currently empty, add one row to this new column. - if (tableModel.columnCount == 1) tableModel.addRow(arrayOf("")) + if (tableModel.columnCount == 1) { + tableModel.addRow(arrayOf("")) + } } /** @@ -74,91 +89,53 @@ class TableCreationDialogWrapper( * @param columnType is the index of the column type. * @param columnIndex is the index of the edited column in the table, starting at 0. */ - @Suppress("KDocUnresolvedReference", "KDocUnresolvedReference") - private val editColumnFun = fun(title: String, columnType: ColumnType, columnIndex: Int) { + private fun editTableColumn(title: String, columnType: ColumnType, columnIndex: Int) { tableModel.setHeaderName(title, columnIndex) + // Edit the column type of the edited column. columnTypes[columnIndex] = columnType - tableModel.fireTableStructureChanged() - } - - private fun getEditColumnActionButton(): AnActionButton = object : AnActionButton("Edit column header", addText(IconUtil.getEditIcon(), "C")) { - - override fun isEnabled() = table.columnCount > 0 - - override fun actionPerformed(e: AnActionEvent) { - if (table.selectedColumn >= 0) { - TableCreationEditColumnDialog( - editColumnFun, - table.selectedColumn, - table.getColumnName(table.selectedColumn), - columnTypes[table.selectedColumn] - ) - } - } - } - - private fun getAddRowActionButton() = object : AnActionButton("Add Row", addText(IconUtil.getAddIcon(), "R")) { - - override fun isEnabled() = table.columnCount > 0 - - override fun actionPerformed(e: AnActionEvent) { - tableModel.addEmptyRow() - } - } - - private fun getRemoveRowActionButton() = object : AnActionButton("Remove Row", addText(IconUtil.getRemoveIcon(), "R")) { - - override fun isEnabled() = table.selectedRow > -1 - - override fun actionPerformed(e: AnActionEvent) { - tableModel.removeRow(table.selectedRow) - } - } - private fun getRemoveColumnActionButton() = object : AnActionButton("Remove Column", addText(IconUtil.getRemoveIcon(), "C")) { - - override fun isEnabled() = table.selectedColumn > -1 - - override fun actionPerformed(e: AnActionEvent) { - tableModel.removeColumn(table.selectedColumn) - } + tableModel.fireTableStructureChanged() } override fun createCenterPanel(): JPanel { - // Decorator that contains the add/remove/edit buttons. val decorator = ToolbarDecorator.createDecorator(table) .setAddAction { - TableCreationEditColumnDialog(addColumnFun, tableModel.columnCount) + TableCreationEditColumnDialog( + { title, columnType, _ -> addTableColumn(title, columnType) }, + tableModel.columnCount + ) } .setAddActionName("Add Column") .setAddIcon(addText(IconUtil.getAddIcon(), "C")) .addExtraAction(getRemoveColumnActionButton()) .addExtraAction(getEditColumnActionButton()) .addExtraAction(getAddRowActionButton()) - .addExtraAction(getRemoveRowActionButton().apply { shortcut = ShortcutSet { arrayOf(KeyboardShortcut(KeyStroke.getKeyStroke("DELETE"), null)) } }) + .addExtraAction(getRemoveRowActionButton().apply { + shortcut = ShortcutSet { + arrayOf(KeyboardShortcut(KeyStroke.getKeyStroke("DELETE"), null)) + } + }) .createPanel() table.addTabCreatesNewRowAction() table.addEnterCreatesNewRowAction() val captionLabel = JBLabel("Caption:") - captionLabel.labelFor = caption + captionLabel.labelFor = lblCaption val referenceLabel = JBLabel("Label:") - referenceLabel.labelFor = reference + referenceLabel.labelFor = txtReference // Add all elements to the panel view. - val panel = JPanel() - panel.apply { + return JPanel().apply { // Add some air around the elements. border = EmptyBorder(8, 8, 8, 8) layout = BoxLayout(this, BoxLayout.Y_AXIS) // Create a panel for the table and its decorator. - val tablePanel = JPanel() - tablePanel.apply { + val tablePanel = JPanel().apply { layout = BorderLayout() add(JScrollPane(table), BorderLayout.WEST) add(decorator, BorderLayout.EAST) @@ -180,21 +157,19 @@ class TableCreationDialogWrapper( add(tablePanelContainer) // Create a panel for the caption box and its label. - val captionPanel = JPanel() - captionPanel.apply { + val captionPanel = JPanel().apply { layout = BoxLayout(this, BoxLayout.X_AXIS) captionLabel.preferredSize = Dimension(80, captionLabel.height) add(captionLabel) - add(caption) + add(lblCaption) } // Create a panel for the label/reference box and its label. - val referencePanel = JPanel() - referencePanel.apply { + val referencePanel = JPanel().apply { layout = BoxLayout(this, BoxLayout.X_AXIS) referenceLabel.preferredSize = Dimension(80, referenceLabel.height) add(referenceLabel) - add(reference) + add(txtReference) } // Actually add all the panels to the main panel. @@ -204,34 +179,14 @@ class TableCreationDialogWrapper( add(Box.createRigidArea(Dimension(0, 8))) add(referencePanel) } - - return panel } /** * See [IconUtil.addText]. */ - fun addText(base: Icon, text: String, scale: Float = 7f): Icon? { - val icon = LayeredIcon(2) - icon.setIcon(base, 0, SwingConstants.NORTH_WEST) - icon.setIcon(IconUtil.textToIcon(text, JLabel(), scale(scale)), 1, SwingConstants.SOUTH_EAST) - return icon - } - - /** - * When clicking OK, the wrapper will validate the form. This means that the table should at least have a header, - * there is some text in the caption text field, and the label text field contains more than just "tab:" (or no - * "tab:" at all, but then it should not be empty). - */ - override fun doValidate(): ValidationInfo? { - return if (tableModel.getColumnNames().size == 0) ValidationInfo("Table cannot be empty.", table) - else if (caption.text.isEmpty()) ValidationInfo("Caption cannot be empty.", caption) - else if (reference.text.isEmpty() || reference.text == "tab:") ValidationInfo("Label cannot be empty", reference) - else { - // 'Save' the current values in the form. - tableInformation = TableInformation(tableModel, columnTypes, caption.text, reference.text) - return null - } + fun addText(base: Icon, text: String, scale: Float = 7f): Icon = LayeredIcon(2).apply { + setIcon(base, 0, SwingConstants.NORTH_WEST) + setIcon(IconUtil.textToIcon(text, JLabel(), JBUIScale.scale(scale)), 1, SwingConstants.SOUTH_EAST) } /** @@ -242,18 +197,20 @@ class TableCreationDialogWrapper( // Get the key stroke for pressing TAB. val keyStroke = KeyStroke.getKeyStroke("TAB") val actionKey = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).get(keyStroke) + // Get the action that currently is under the TAB key. val action = actionMap[actionKey] - val actionWrapper = object : AbstractAction() { override fun actionPerformed(e: ActionEvent?) { val table = this@addTabCreatesNewRowAction + // When we're in the last column of the last row, add a new row before calling the usual action. if (table.selectionModel.leadSelectionIndex == table.rowCount - 1 && table.columnModel.selectionModel.leadSelectionIndex == table.columnCount - 1 ) { tableModel.addEmptyRow() } + // Perform the usual action. action.actionPerformed(e) } @@ -292,4 +249,55 @@ class TableCreationDialogWrapper( actionMap.put("enter", actionWrapper) } + + private fun getEditColumnActionButton(): AnActionButton { + return object : AnActionButton("Edit column header", addText(IconUtil.getEditIcon(), "C")) { + + override fun isEnabled() = table.columnCount > 0 + + override fun actionPerformed(e: AnActionEvent) { + if (table.selectedColumn >= 0) { + TableCreationEditColumnDialog( + { title, columnType, _ -> addTableColumn(title, columnType) }, + table.selectedColumn, + table.getColumnName(table.selectedColumn), + columnTypes[table.selectedColumn] + ) + } + } + } + } + + private fun getAddRowActionButton(): AnActionButton { + return object : AnActionButton("Add Row", addText(IconUtil.getAddIcon(), "R")) { + + override fun isEnabled() = table.columnCount > 0 + + override fun actionPerformed(e: AnActionEvent) { + tableModel.addEmptyRow() + } + } + } + + private fun getRemoveRowActionButton(): AnActionButton { + return object : AnActionButton("Remove Row", addText(IconUtil.getRemoveIcon(), "R")) { + + override fun isEnabled() = table.selectedRow > -1 + + override fun actionPerformed(e: AnActionEvent) { + tableModel.removeRow(table.selectedRow) + } + } + } + + private fun getRemoveColumnActionButton(): AnActionButton { + return object : AnActionButton("Remove Column", addText(IconUtil.getRemoveIcon(), "C")) { + + override fun isEnabled() = table.selectedColumn > -1 + + override fun actionPerformed(e: AnActionEvent) { + tableModel.removeColumn(table.selectedColumn) + } + } + } } \ No newline at end of file diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt index 6288d344f..3a6968179 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt @@ -10,18 +10,29 @@ import javax.swing.JPanel /** * Dialog to add a new column to the table. * - * @param onOkFunction The function to execute when clicking the OK button. - * @param editingColumn The index of the column being edited. - * @param columnName The name of the column that is being edited. Default is the empty string, the title of a column that does - * not yet exist. - * @param columnType The [ColumnType] of the column that is being edited. Default is a text column. - * * @author Abby Berkers */ class TableCreationEditColumnDialog( - private val onOkFunction: (String, ColumnType, Int) -> Unit, + + /** + * The function to execute when clicking the OK button. + */ + private val onOkFunction: (title: String, columnType: ColumnType, columnIndex: Int) -> Unit, + + /** + * The index of the column being edited. + */ private val editingColumn: Int, + + /** + * The name of the column that is being edited. Default is the empty string, the title of a column that does + * not yet exist. + */ private val columnName: String = "", + + /** + * The [ColumnType] of the column that is being edited. Default is a text column. + */ private val columnType: ColumnType = ColumnType.TEXT_COLUMN ) { @@ -34,6 +45,7 @@ class TableCreationEditColumnDialog( // A combobox to select the column type. val columnTypeComboBox = JComboBox(ColumnType.values().map { it.displayName }.toTypedArray()) + // Select the old type of the editing column. columnTypeComboBox.selectedIndex = ColumnType.values().indexOf(columnType) val columnTypeLabel = JBLabel("Column type") diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt index 7e4bd8e3e..b3b6ba4a2 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt @@ -35,7 +35,7 @@ class TableCreationTableModel : DefaultTableModel() { * Adds an empty row to the table. */ fun addEmptyRow() { - val emptyRow = (0 until columnCount).map { "" }.toTypedArray() + val emptyRow = Array(columnCount) { "" } addRow(emptyRow) } diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableInformation.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableInformation.kt index 98156e156..4e69efb35 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableInformation.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableInformation.kt @@ -3,17 +3,28 @@ package nl.hannahsten.texifyidea.action.wizard.table /** * Stores all information about a table. * - * @param tableModel contains all information about the contents of the table. That is, the column names and the table - * entries. - * @param columnTypes contains the type of each column. - * @param caption contains the caption to go along with the table. - * @param label contains the label that is to be used to reference to the table. - * * @author Abby Berkers */ data class TableInformation( + + /** + * Contains all information about the contents of the table. + * That is, the column names and the table entries. + */ val tableModel: TableCreationTableModel, + + /** + * Contains the type of each column. + */ val columnTypes: List, + + /** + * Contains the caption to go along with the table. + */ val caption: String, + + /** + * Contains the label that is to be used to reference the table. + */ val label: String ) \ No newline at end of file From a1b98b915435b7e8eb1d18b7ecfd92f2f11bee56 Mon Sep 17 00:00:00 2001 From: Hannah Schellekens Date: Mon, 11 Jan 2021 15:51:41 +0100 Subject: [PATCH 3/8] Pimped the Table creation wizard ui: - Table is now properly visible. - Structured the code a bit more. - Improved layout usage. --- .../InsertGraphicWizardDialogWrapper.kt | 46 +----- .../table/TableCreationDialogWrapper.kt | 154 +++++++++--------- .../table/TableCreationEditColumnDialog.kt | 27 ++- .../texifyidea/util/UserInterface.kt | 45 +++++ 4 files changed, 132 insertions(+), 140 deletions(-) diff --git a/src/nl/hannahsten/texifyidea/action/wizard/graphic/InsertGraphicWizardDialogWrapper.kt b/src/nl/hannahsten/texifyidea/action/wizard/graphic/InsertGraphicWizardDialogWrapper.kt index 7dd3192ea..99e197c4a 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/graphic/InsertGraphicWizardDialogWrapper.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/graphic/InsertGraphicWizardDialogWrapper.kt @@ -13,10 +13,7 @@ import com.intellij.ui.components.fields.ExpandableTextField import com.intellij.ui.components.panels.HorizontalLayout import nl.hannahsten.texifyidea.lang.graphic.CaptionLocation import nl.hannahsten.texifyidea.lang.graphic.FigureLocation -import nl.hannahsten.texifyidea.util.Magic -import nl.hannahsten.texifyidea.util.addKeyReleasedListener -import nl.hannahsten.texifyidea.util.addTextChangeListener -import nl.hannahsten.texifyidea.util.setInputFilter +import nl.hannahsten.texifyidea.util.* import java.awt.BorderLayout import java.awt.Dimension import javax.swing.* @@ -27,14 +24,6 @@ import javax.swing.border.EmptyBorder */ open class InsertGraphicWizardDialogWrapper(val initialFilePath: String = "") : DialogWrapper(true) { - companion object { - - /** - * The amount of pixels between the left pane border and the contorls. - */ - private const val CONTROL_LEFT_PADDING = 16 - } - /** * Stores the path to the graphics file. */ @@ -248,39 +237,6 @@ open class InsertGraphicWizardDialogWrapper(val initialFilePath: String = "") : add(Box.createRigidArea(Dimension(0, margin))) } - /** - * Adds a component to the panel with a label before it. - * - * @param component - * The component to add to the panel. - * @param description - * The label to put before the component. - * @param labelWidth - * The fixed label width, or `null` to use the label's inherent size. - */ - private fun JPanel.addLabeledComponent(component: JComponent, description: String, labelWidth: Int? = null): JPanel { - // Uses a border layout with West for the label and Center for the control itself. - // East is reserved for suffix elements. - val pane = JPanel(BorderLayout()).apply { - val label = JBLabel(description).apply { - // Left padding. - border = EmptyBorder(0, CONTROL_LEFT_PADDING, 0, 0) - - // Custom width if specified. - labelWidth?.let { - preferredSize = Dimension(it, height) - } - - // Align top. - alignmentY = 0.0f - } - add(label, BorderLayout.WEST) - add(component, BorderLayout.CENTER) - } - add(pane) - return pane - } - private fun updateFigureControlsState() { val enabled = checkPlaceInFigure.isSelected diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt index 40e795f87..b556e836e 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt @@ -4,14 +4,18 @@ import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.KeyboardShortcut import com.intellij.openapi.actionSystem.ShortcutSet import com.intellij.openapi.ui.DialogWrapper +import com.intellij.openapi.ui.ValidationInfo import com.intellij.ui.AnActionButton import com.intellij.ui.LayeredIcon import com.intellij.ui.ToolbarDecorator import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBTextField +import com.intellij.ui.components.panels.HorizontalLayout +import com.intellij.ui.components.panels.VerticalLayout import com.intellij.ui.scale.JBUIScale import com.intellij.ui.table.JBTable import com.intellij.util.IconUtil +import nl.hannahsten.texifyidea.util.addLabeledComponent import java.awt.* import java.awt.event.ActionEvent import java.awt.event.KeyEvent @@ -38,12 +42,15 @@ open class TableCreationDialogWrapper : DialogWrapper(true) { /** * The table component that shows the table. */ - private val table = JBTable(tableModel) + private val table = JBTable(tableModel).apply { + addTabCreatesNewRowAction() + addEnterCreatesNewRowAction() + } /** * The text field that contains the caption for the table. */ - private val lblCaption = JBTextField() + private val txtCaption = JBTextField() /** * The text field that contains the label for the table. It has a default value "tab:" to encourage usage @@ -98,87 +105,62 @@ open class TableCreationDialogWrapper : DialogWrapper(true) { tableModel.fireTableStructureChanged() } - override fun createCenterPanel(): JPanel { - // Decorator that contains the add/remove/edit buttons. - val decorator = ToolbarDecorator.createDecorator(table) - .setAddAction { - TableCreationEditColumnDialog( - { title, columnType, _ -> addTableColumn(title, columnType) }, - tableModel.columnCount - ) - } - .setAddActionName("Add Column") - .setAddIcon(addText(IconUtil.getAddIcon(), "C")) - .addExtraAction(getRemoveColumnActionButton()) - .addExtraAction(getEditColumnActionButton()) - .addExtraAction(getAddRowActionButton()) - .addExtraAction(getRemoveRowActionButton().apply { - shortcut = ShortcutSet { - arrayOf(KeyboardShortcut(KeyStroke.getKeyStroke("DELETE"), null)) - } - }) - .createPanel() - - table.addTabCreatesNewRowAction() - table.addEnterCreatesNewRowAction() - - val captionLabel = JBLabel("Caption:") - captionLabel.labelFor = lblCaption - - val referenceLabel = JBLabel("Label:") - referenceLabel.labelFor = txtReference - - // Add all elements to the panel view. - return JPanel().apply { - // Add some air around the elements. - border = EmptyBorder(8, 8, 8, 8) - layout = BoxLayout(this, BoxLayout.Y_AXIS) - - // Create a panel for the table and its decorator. - val tablePanel = JPanel().apply { - layout = BorderLayout() - add(JScrollPane(table), BorderLayout.WEST) - add(decorator, BorderLayout.EAST) - } + override fun createCenterPanel(): JPanel = JPanel(BorderLayout(8, 8)).apply { + // Put help text below table + add(createTablePanelContainer(), BorderLayout.CENTER) - // Help text - val helpText = JBLabel("Press tab to go to the next cell or row, press enter to go to the next row.") - helpText.foreground = Color.GRAY - - // Put help text below table - val tablePanelContainer = JPanel(GridBagLayout()) - val constraints = GridBagConstraints() - constraints.gridx = 0 - constraints.gridy = GridBagConstraints.RELATIVE - tablePanelContainer.apply { - add(tablePanel, constraints) - add(helpText, constraints) - } - add(tablePanelContainer) - - // Create a panel for the caption box and its label. - val captionPanel = JPanel().apply { - layout = BoxLayout(this, BoxLayout.X_AXIS) - captionLabel.preferredSize = Dimension(80, captionLabel.height) - add(captionLabel) - add(lblCaption) - } + // Create labels. + add(JPanel(VerticalLayout(8)).apply { + addLabeledComponent(txtCaption, "Caption:", labelWidth = 64, leftPadding = 0) + addLabeledComponent(txtReference, "Label:", labelWidth = 64, leftPadding = 0) + }, BorderLayout.SOUTH) + } - // Create a panel for the label/reference box and its label. - val referencePanel = JPanel().apply { - layout = BoxLayout(this, BoxLayout.X_AXIS) - referenceLabel.preferredSize = Dimension(80, referenceLabel.height) - add(referenceLabel) - add(txtReference) + /** + * Generates table and the toolbaar buttons. + */ + private fun createToolbarDecorator() = ToolbarDecorator.createDecorator(table) + .setAddAction { + TableCreationEditColumnDialog( + { title, columnType, _ -> addTableColumn(title, columnType) }, + tableModel.columnCount + ) } + .setAddActionName("Add Column") + .setAddIcon(addText(IconUtil.getAddIcon(), "C")) + .addExtraAction(getRemoveColumnActionButton()) + .addExtraAction(getEditColumnActionButton()) + .addExtraAction(getAddRowActionButton()) + .addExtraAction(getRemoveRowActionButton().apply { + shortcut = ShortcutSet { + arrayOf(KeyboardShortcut(KeyStroke.getKeyStroke("DELETE"), null)) + } + }) + .createPanel() - // Actually add all the panels to the main panel. - // Add some air between components. - add(Box.createRigidArea(Dimension(0, 8))) - add(captionPanel) - add(Box.createRigidArea(Dimension(0, 8))) - add(referencePanel) - } + /** + * Panel containing the table and its controls. + */ + private fun createTablePanel() = JPanel(BorderLayout()).apply { + add(createToolbarDecorator(), BorderLayout.CENTER) + } + + /** + * Creates a hint label describing the table controls. + */ + private fun createHelpText() = JBLabel().apply { + text = "Press tab to go to the next cell or row, press enter to go to the next row." + foreground = Color.GRAY + } + + /** + * The panel containing everything related to the table. + */ + private fun createTablePanelContainer() = JPanel(BorderLayout()).apply { + minimumSize = Dimension(480, 320) + + add(createTablePanel(), BorderLayout.CENTER) + add(createHelpText(), BorderLayout.SOUTH) } /** @@ -250,6 +232,20 @@ open class TableCreationDialogWrapper : DialogWrapper(true) { actionMap.put("enter", actionWrapper) } + /** + * Saves all data in [tableInformation]. + * Every input is always valid: this will mean empty icons. + */ + override fun doValidate(): ValidationInfo? { + tableInformation = TableInformation( + tableModel, + columnTypes, + txtCaption.text.trim(), + txtReference.text.trim() + ) + return null + } + private fun getEditColumnActionButton(): AnActionButton { return object : AnActionButton("Edit column header", addText(IconUtil.getEditIcon(), "C")) { diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt index 3a6968179..cb825b85b 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt @@ -4,6 +4,9 @@ import com.intellij.openapi.ui.DialogBuilder import com.intellij.openapi.ui.DialogWrapper import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBTextField +import com.intellij.ui.components.panels.VerticalLayout +import nl.hannahsten.texifyidea.util.addLabeledComponent +import javax.swing.BoxLayout import javax.swing.JComboBox import javax.swing.JPanel @@ -39,27 +42,19 @@ class TableCreationEditColumnDialog( init { DialogBuilder().apply { // Text field for the name of the column, with the old name of the editing column filled in. - val columnNameField = JBTextField(columnName) - val columnNameLabel = JBLabel("Column name") - columnNameLabel.labelFor = columnNameField + val txtColumnName = JBTextField(columnName) // A combobox to select the column type. - val columnTypeComboBox = JComboBox(ColumnType.values().map { it.displayName }.toTypedArray()) - - // Select the old type of the editing column. - columnTypeComboBox.selectedIndex = ColumnType.values().indexOf(columnType) - val columnTypeLabel = JBLabel("Column type") - columnTypeLabel.labelFor = columnTypeComboBox + val cboxColumnType = JComboBox(ColumnType.values().map { it.displayName }.toTypedArray()) + cboxColumnType.selectedIndex = ColumnType.values().indexOf(columnType) // Add UI elements. - val panel = JPanel().apply { - add(columnNameLabel) - add(columnNameField) - add(columnTypeLabel) - add(columnTypeComboBox) + val panel = JPanel(VerticalLayout(8)).apply { + addLabeledComponent(txtColumnName, "Column title:", labelWidth = 96, leftPadding = 0) + addLabeledComponent(cboxColumnType, "Column type:", labelWidth = 96, leftPadding = 0) } setCenterPanel(panel) - setPreferredFocusComponent(columnNameField) + setPreferredFocusComponent(txtColumnName) addOkAction() setOkOperation { @@ -74,7 +69,7 @@ class TableCreationEditColumnDialog( } if (show() == DialogWrapper.OK_EXIT_CODE) { - onOkFunction(columnNameField.text, ColumnType.values()[columnTypeComboBox.selectedIndex], editingColumn) + onOkFunction(txtColumnName.text, ColumnType.values()[cboxColumnType.selectedIndex], editingColumn) } } } diff --git a/src/nl/hannahsten/texifyidea/util/UserInterface.kt b/src/nl/hannahsten/texifyidea/util/UserInterface.kt index 54bfb1764..5217bab81 100644 --- a/src/nl/hannahsten/texifyidea/util/UserInterface.kt +++ b/src/nl/hannahsten/texifyidea/util/UserInterface.kt @@ -6,9 +6,16 @@ import com.intellij.openapi.ui.popup.Balloon import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.openapi.wm.WindowManager import com.intellij.ui.awt.RelativePoint +import com.intellij.ui.components.JBLabel +import nl.hannahsten.texifyidea.action.wizard.graphic.InsertGraphicWizardDialogWrapper +import java.awt.BorderLayout +import java.awt.Dimension import java.awt.event.KeyAdapter import java.awt.event.KeyEvent import java.awt.event.KeyListener +import javax.swing.JComponent +import javax.swing.JPanel +import javax.swing.border.EmptyBorder import javax.swing.event.DocumentEvent import javax.swing.event.DocumentListener import javax.swing.text.JTextComponent @@ -130,4 +137,42 @@ fun JTextComponent.setInputFilter(allowedCharacters: Set) = addKeyTypedLis if (it.keyChar !in allowedCharacters) { it.consume() } +} + +/** + * Adds a component to the panel with a label before it. + * + * @param component + * The component to add to the panel. + * @param description + * The label to put before the component. + * @param labelWidth + * The fixed label width, or `null` to use the label's inherent size. + */ +fun JPanel.addLabeledComponent( + component: JComponent, + description: String, + labelWidth: Int? = null, + leftPadding: Int = 16 +): JPanel { + // Uses a border layout with West for the label and Center for the control itself. + // East is reserved for suffix elements. + val pane = JPanel(BorderLayout()).apply { + val label = JBLabel(description).apply { + // Left padding. + border = EmptyBorder(0, leftPadding, 0, 0) + + // Custom width if specified. + labelWidth?.let { + preferredSize = Dimension(it, height) + } + + // Align top. + alignmentY = 0.0f + } + add(label, BorderLayout.WEST) + add(component, BorderLayout.CENTER) + } + add(pane) + return pane } \ No newline at end of file From 581ae5026fa0acb51957651ffc188de3ac7826d8 Mon Sep 17 00:00:00 2001 From: Hannah Schellekens Date: Mon, 11 Jan 2021 18:11:17 +0100 Subject: [PATCH 4/8] Pasted html tables open and fill in the Table Creation Wizard, is disabled when shift is pressed when pasting. --- resources/META-INF/plugin.xml | 1 + .../wizard/table/LatexTableWizardAction.kt | 19 ++- .../table/TableCreationDialogWrapper.kt | 10 +- .../wizard/table/TableCreationTableModel.kt | 6 +- .../texifyidea/editor/TablePasteProvider.kt | 122 ++++++++++++++++++ .../hannahsten/texifyidea/util/Clipboard.kt | 20 +++ .../hannahsten/texifyidea/util/Collections.kt | 7 +- 7 files changed, 175 insertions(+), 10 deletions(-) create mode 100644 src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt create mode 100644 src/nl/hannahsten/texifyidea/util/Clipboard.kt diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 8316adb0d..b6cb433b6 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -474,6 +474,7 @@ + diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt index 7b2d93113..903013e88 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt @@ -4,6 +4,11 @@ import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.editor.Document +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.DialogWrapper +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiFile import nl.hannahsten.texifyidea.action.insert.InsertTable import nl.hannahsten.texifyidea.lang.LatexPackage import nl.hannahsten.texifyidea.util.caretOffset @@ -21,17 +26,15 @@ import java.util.* */ class LatexTableWizardAction : AnAction() { - override fun actionPerformed(e: AnActionEvent) { - val file = e.getData(PlatformDataKeys.VIRTUAL_FILE) ?: return - val project = e.getData(PlatformDataKeys.PROJECT) - val editor = project?.currentTextEditor() ?: return + fun executeAction(file: VirtualFile, project: Project, defaultDialogWrapper: TableCreationDialogWrapper? = null) { + val editor = project.currentTextEditor() ?: return ?: return val document = editor.editor.document // Get the indentation from the current line. val indent = document.lineIndentationByOffset(editor.editor.caretOffset()) // Create the dialog. - val dialogWrapper = TableCreationDialogWrapper() + val dialogWrapper = defaultDialogWrapper ?: TableCreationDialogWrapper() // If the user pressed OK, do stuff. if (dialogWrapper.showAndGet()) { @@ -53,6 +56,12 @@ class LatexTableWizardAction : AnAction() { } } + override fun actionPerformed(e: AnActionEvent) { + val file = e.getData(PlatformDataKeys.VIRTUAL_FILE) ?: return + val project = e.getData(PlatformDataKeys.PROJECT) ?: return + executeAction(file, project) + } + /** * Convert the table information to a latex table that can be inserted into the file. * diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt index b556e836e..ecc356c1f 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt @@ -21,23 +21,27 @@ import java.awt.event.ActionEvent import java.awt.event.KeyEvent import javax.swing.* import javax.swing.border.EmptyBorder +import javax.swing.table.TableModel /** * Wrapper that contains the table creation dialog. * * @author Abby Berkers */ -open class TableCreationDialogWrapper : DialogWrapper(true) { +open class TableCreationDialogWrapper( + initialColumnTypes: List? = null, + initialTableModel: TableCreationTableModel? = null +) : DialogWrapper(true) { /** * Types of the columns of the table, see [ColumnType], always start with an empty table. */ - private val columnTypes = mutableListOf() + private val columnTypes = initialColumnTypes?.toMutableList() ?: mutableListOf() /** * The model of the table, always start with an empty table. */ - private val tableModel = TableCreationTableModel() + private val tableModel = initialTableModel ?: TableCreationTableModel() /** * The table component that shows the table. diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt index b3b6ba4a2..ed85b12ca 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt @@ -6,7 +6,11 @@ import javax.swing.table.DefaultTableModel /** * @author Abby Berkers */ -class TableCreationTableModel : DefaultTableModel() { +class TableCreationTableModel : DefaultTableModel { + + constructor(data: Vector>, columnNames: Vector) : super(data, columnNames) + + constructor() : this(Vector(), Vector()) /** * Remove a column and its header from the table. diff --git a/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt b/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt new file mode 100644 index 000000000..a5e6844da --- /dev/null +++ b/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt @@ -0,0 +1,122 @@ +package nl.hannahsten.texifyidea.editor + +import com.intellij.ide.PasteProvider +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.actionSystem.PlatformDataKeys +import com.intellij.openapi.editor.actions.PasteAction +import jnr.a64asm.Shift +import nl.hannahsten.texifyidea.action.wizard.table.ColumnType +import nl.hannahsten.texifyidea.action.wizard.table.LatexTableWizardAction +import nl.hannahsten.texifyidea.action.wizard.table.TableCreationDialogWrapper +import nl.hannahsten.texifyidea.action.wizard.table.TableCreationTableModel +import nl.hannahsten.texifyidea.file.LatexFileType +import nl.hannahsten.texifyidea.util.Clipboard +import nl.hannahsten.texifyidea.util.toVector +import org.jsoup.Jsoup +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import java.awt.datatransfer.DataFlavor +import java.lang.StringBuilder +import java.util.* + +/** + * Pastes the table html into a Insert Table Wizard if applicable. + * + * @author Hannah Schellekens + */ +open class TablePasteProvider : PasteProvider { + + override fun performPaste(dataContext: DataContext) { + val file = dataContext.getData(PlatformDataKeys.VIRTUAL_FILE) ?: return + val project = dataContext.getData(PlatformDataKeys.PROJECT) ?: return + val clipboardHtml = dataContext.transferableHtml() ?: return + val html = Clipboard.extractHtmlFromClipboard(clipboardHtml) ?: return + val tableDialog = Jsoup.parse(html).toTableDialogWrapper() ?: return + + LatexTableWizardAction().executeAction(file, project, tableDialog) + } + + override fun isPastePossible(dataContext: DataContext): Boolean { + val file = dataContext.getData(PlatformDataKeys.PSI_FILE) ?: return false + if (file.fileType != LatexFileType) return false + if (ShiftTracker.isShiftPressed()) return false + + val pasteData = dataContext.transferableHtml() ?: return false + return pasteData.contains("> and headers. + val header = rows.first().select("td").map { it.text() }.toVector() + val content: Vector> = rows.drop(1).map { tr -> + tr.select("td").map { td -> td.handleHtmlFormatting() as Any? }.toVector() + }.toVector() + + // Find the type of column automatically. + val contentRows = rows.drop(1) + val columnTypes = (0 until width).map { col -> + // Check if all contents of the column (except the header) can be converted to a number. + // When that's the case => it's a number column. All other cases, text. Ignoring the Math option + // as the table information is most probably something outside of a latex context. + if (contentRows.all { it.select("td").getOrNull(col)?.text()?.toDoubleOrNull() != null }) { + ColumnType.NUMBERS_COLUMN + } + else ColumnType.TEXT_COLUMN + } + + return TableCreationDialogWrapper( + columnTypes, + TableCreationTableModel(content, header) + ) + } + + /** + * Converts // tags to latex formatting commands. + * `this` is a HTML Element. + */ + private fun Element.handleHtmlFormatting(): String { + val prefix = StringBuilder() + val suffix = StringBuilder() + + if (select("b").isNotEmpty()) { + prefix.append("\\textbf{") + suffix.append("}") + } + if (select("i").isNotEmpty()) { + prefix.append("\\textit{") + suffix.append("}") + } + if (select("u").isNotEmpty()) { + prefix.append("\\underline{") + suffix.append("}") + } + + return prefix + .append(text()) + .append(suffix.toString()) + .toString() + } +} \ No newline at end of file diff --git a/src/nl/hannahsten/texifyidea/util/Clipboard.kt b/src/nl/hannahsten/texifyidea/util/Clipboard.kt new file mode 100644 index 000000000..05c8cc1cc --- /dev/null +++ b/src/nl/hannahsten/texifyidea/util/Clipboard.kt @@ -0,0 +1,20 @@ +package nl.hannahsten.texifyidea.util + +/** + * @author Hannah Schellekens + */ +object Clipboard { + + /** + * Takes the complete clipboard contents (must have an html data flavor) and extracts the html (thus dropping + * the header). + * + * @return null when it could not find html + */ + @JvmStatic + fun extractHtmlFromClipboard(clipboardContents: String): String? { + return clipboardContents.indexOf("= 0 } + ?.let { clipboardContents.substring(it) } + } +} \ No newline at end of file diff --git a/src/nl/hannahsten/texifyidea/util/Collections.kt b/src/nl/hannahsten/texifyidea/util/Collections.kt index 3f080ce27..60d7ecc58 100644 --- a/src/nl/hannahsten/texifyidea/util/Collections.kt +++ b/src/nl/hannahsten/texifyidea/util/Collections.kt @@ -147,4 +147,9 @@ fun Stream.set(): Set = this.mutableSet() /** * Collects stream to [MutableSet] */ -fun Stream.mutableSet(): MutableSet = this.collect(Collectors.toSet()) \ No newline at end of file +fun Stream.mutableSet(): MutableSet = this.collect(Collectors.toSet()) + +/** + * Converts the collection to a vector. + */ +fun Collection.toVector() = Vector(this) \ No newline at end of file From 07de42ea9bfa78f96c4668ce444425b86c36e95f Mon Sep 17 00:00:00 2001 From: Hannah Schellekens Date: Mon, 11 Jan 2021 20:24:25 +0100 Subject: [PATCH 5/8] Table wizard: Fixed edit column not working and paster not recognising th --- .../wizard/table/TableCreationDialogWrapper.kt | 2 +- .../texifyidea/editor/TablePasteProvider.kt | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt index ecc356c1f..6f91ee650 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt @@ -258,7 +258,7 @@ open class TableCreationDialogWrapper( override fun actionPerformed(e: AnActionEvent) { if (table.selectedColumn >= 0) { TableCreationEditColumnDialog( - { title, columnType, _ -> addTableColumn(title, columnType) }, + { title, columnType, columnIndex -> editTableColumn(title, columnType, columnIndex) }, table.selectedColumn, table.getColumnName(table.selectedColumn), columnTypes[table.selectedColumn] diff --git a/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt b/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt index a5e6844da..bc97476d0 100644 --- a/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt +++ b/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt @@ -65,14 +65,14 @@ open class TablePasteProvider : PasteProvider { private fun Document.toTableDialogWrapper(): TableCreationDialogWrapper? { val rows = select("table tr") val height = rows.size - val width = rows.firstOrNull()?.select("td")?.size ?: 0 + val width = rows.firstOrNull()?.select("td, th")?.size ?: 0 if (height == 0 && width == 0) return null // Convert html to data vector Vector> and headers. - val header = rows.first().select("td").map { it.text() }.toVector() + val header = rows.first().select("td, th").map { it.text() }.toVector() val content: Vector> = rows.drop(1).map { tr -> - tr.select("td").map { td -> td.handleHtmlFormatting() as Any? }.toVector() + tr.select("td, th").map { td -> td.handleHtmlFormatting() as Any? }.toVector() }.toVector() // Find the type of column automatically. @@ -81,7 +81,7 @@ open class TablePasteProvider : PasteProvider { // Check if all contents of the column (except the header) can be converted to a number. // When that's the case => it's a number column. All other cases, text. Ignoring the Math option // as the table information is most probably something outside of a latex context. - if (contentRows.all { it.select("td").getOrNull(col)?.text()?.toDoubleOrNull() != null }) { + if (contentRows.all { it.select("td, th").getOrNull(col)?.text()?.toDoubleOrNull() != null }) { ColumnType.NUMBERS_COLUMN } else ColumnType.TEXT_COLUMN @@ -101,11 +101,11 @@ open class TablePasteProvider : PasteProvider { val prefix = StringBuilder() val suffix = StringBuilder() - if (select("b").isNotEmpty()) { + if (select("b, strong").isNotEmpty()) { prefix.append("\\textbf{") suffix.append("}") } - if (select("i").isNotEmpty()) { + if (select("i, em").isNotEmpty()) { prefix.append("\\textit{") suffix.append("}") } From dd8f5dc34c03228550e2d31d864a43c5d4212ee0 Mon Sep 17 00:00:00 2001 From: Hannah Schellekens Date: Mon, 11 Jan 2021 20:28:12 +0100 Subject: [PATCH 6/8] Optimized imports. --- .../wizard/graphic/InsertGraphicWizardDialogWrapper.kt | 8 ++++---- .../action/wizard/table/LatexTableWizardAction.kt | 3 --- .../action/wizard/table/TableCreationDialogWrapper.kt | 3 --- .../action/wizard/table/TableCreationEditColumnDialog.kt | 2 -- src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt | 2 -- src/nl/hannahsten/texifyidea/util/UserInterface.kt | 1 - 6 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/nl/hannahsten/texifyidea/action/wizard/graphic/InsertGraphicWizardDialogWrapper.kt b/src/nl/hannahsten/texifyidea/action/wizard/graphic/InsertGraphicWizardDialogWrapper.kt index 99e197c4a..894e9811f 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/graphic/InsertGraphicWizardDialogWrapper.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/graphic/InsertGraphicWizardDialogWrapper.kt @@ -7,17 +7,17 @@ import com.intellij.openapi.ui.TextBrowseFolderListener import com.intellij.openapi.ui.TextFieldWithBrowseButton import com.intellij.ui.TitledSeparator import com.intellij.ui.components.JBCheckBox -import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBTextField import com.intellij.ui.components.fields.ExpandableTextField import com.intellij.ui.components.panels.HorizontalLayout import nl.hannahsten.texifyidea.lang.graphic.CaptionLocation import nl.hannahsten.texifyidea.lang.graphic.FigureLocation import nl.hannahsten.texifyidea.util.* -import java.awt.BorderLayout import java.awt.Dimension -import javax.swing.* -import javax.swing.border.EmptyBorder +import javax.swing.Box +import javax.swing.BoxLayout +import javax.swing.JPanel +import javax.swing.JTextField /** * @author Hannah Schellekens diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt index 903013e88..a7cfc7b31 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt @@ -4,11 +4,8 @@ import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.command.WriteCommandAction -import com.intellij.openapi.editor.Document import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiFile import nl.hannahsten.texifyidea.action.insert.InsertTable import nl.hannahsten.texifyidea.lang.LatexPackage import nl.hannahsten.texifyidea.util.caretOffset diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt index 6f91ee650..6b28ecbeb 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationDialogWrapper.kt @@ -10,7 +10,6 @@ import com.intellij.ui.LayeredIcon import com.intellij.ui.ToolbarDecorator import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBTextField -import com.intellij.ui.components.panels.HorizontalLayout import com.intellij.ui.components.panels.VerticalLayout import com.intellij.ui.scale.JBUIScale import com.intellij.ui.table.JBTable @@ -20,8 +19,6 @@ import java.awt.* import java.awt.event.ActionEvent import java.awt.event.KeyEvent import javax.swing.* -import javax.swing.border.EmptyBorder -import javax.swing.table.TableModel /** * Wrapper that contains the table creation dialog. diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt index cb825b85b..3ad3029a4 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationEditColumnDialog.kt @@ -2,11 +2,9 @@ package nl.hannahsten.texifyidea.action.wizard.table import com.intellij.openapi.ui.DialogBuilder import com.intellij.openapi.ui.DialogWrapper -import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBTextField import com.intellij.ui.components.panels.VerticalLayout import nl.hannahsten.texifyidea.util.addLabeledComponent -import javax.swing.BoxLayout import javax.swing.JComboBox import javax.swing.JPanel diff --git a/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt b/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt index bc97476d0..7cc19d24f 100644 --- a/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt +++ b/src/nl/hannahsten/texifyidea/editor/TablePasteProvider.kt @@ -4,7 +4,6 @@ import com.intellij.ide.PasteProvider import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.editor.actions.PasteAction -import jnr.a64asm.Shift import nl.hannahsten.texifyidea.action.wizard.table.ColumnType import nl.hannahsten.texifyidea.action.wizard.table.LatexTableWizardAction import nl.hannahsten.texifyidea.action.wizard.table.TableCreationDialogWrapper @@ -16,7 +15,6 @@ import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Element import java.awt.datatransfer.DataFlavor -import java.lang.StringBuilder import java.util.* /** diff --git a/src/nl/hannahsten/texifyidea/util/UserInterface.kt b/src/nl/hannahsten/texifyidea/util/UserInterface.kt index 5217bab81..1db531e70 100644 --- a/src/nl/hannahsten/texifyidea/util/UserInterface.kt +++ b/src/nl/hannahsten/texifyidea/util/UserInterface.kt @@ -7,7 +7,6 @@ import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.openapi.wm.WindowManager import com.intellij.ui.awt.RelativePoint import com.intellij.ui.components.JBLabel -import nl.hannahsten.texifyidea.action.wizard.graphic.InsertGraphicWizardDialogWrapper import java.awt.BorderLayout import java.awt.Dimension import java.awt.event.KeyAdapter From 6bd503a5784f6c7b23087af690bd88033ad4b705 Mon Sep 17 00:00:00 2001 From: Hannah Schellekens Date: Mon, 11 Jan 2021 20:51:30 +0100 Subject: [PATCH 7/8] Linting. --- .../texifyidea/action/wizard/table/TableCreationTableModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt index ed85b12ca..d932dd7f2 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/TableCreationTableModel.kt @@ -39,7 +39,7 @@ class TableCreationTableModel : DefaultTableModel { * Adds an empty row to the table. */ fun addEmptyRow() { - val emptyRow = Array(columnCount) { "" } + val emptyRow = Array(columnCount) { "" } addRow(emptyRow) } From 9b0de6bc37244a24f968e734c981fbe125a456de Mon Sep 17 00:00:00 2001 From: Hannah Schellekens Date: Tue, 12 Jan 2021 14:59:20 +0100 Subject: [PATCH 8/8] Suggestions. --- .../texifyidea/action/wizard/table/LatexTableWizardAction.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt index a7cfc7b31..dc401b000 100644 --- a/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt +++ b/src/nl/hannahsten/texifyidea/action/wizard/table/LatexTableWizardAction.kt @@ -24,7 +24,7 @@ import java.util.* class LatexTableWizardAction : AnAction() { fun executeAction(file: VirtualFile, project: Project, defaultDialogWrapper: TableCreationDialogWrapper? = null) { - val editor = project.currentTextEditor() ?: return ?: return + val editor = project.currentTextEditor() ?: return val document = editor.editor.document // Get the indentation from the current line. @@ -45,7 +45,7 @@ class LatexTableWizardAction : AnAction() { // Insert the booktabs package. WriteCommandAction.runWriteCommandAction( project, - "Insert table", + "Insert Table", "LaTeX", Runnable { file.psiFile(project)?.insertUsepackage(LatexPackage.BOOKTABS) }, file.psiFile(project)