diff --git a/main/src/com/google/gridworks/GridworksServlet.java b/main/src/com/google/gridworks/GridworksServlet.java index 17c7723b3..8c21259aa 100644 --- a/main/src/com/google/gridworks/GridworksServlet.java +++ b/main/src/com/google/gridworks/GridworksServlet.java @@ -78,6 +78,7 @@ public class GridworksServlet extends Butterfly { {"add-column", "com.google.gridworks.commands.column.AddColumnCommand"}, {"remove-column", "com.google.gridworks.commands.column.RemoveColumnCommand"}, {"rename-column", "com.google.gridworks.commands.column.RenameColumnCommand"}, + {"move-column", "com.google.gridworks.commands.column.MoveColumnCommand"}, {"split-column", "com.google.gridworks.commands.column.SplitColumnCommand"}, {"extend-data", "com.google.gridworks.commands.column.ExtendDataCommand"}, diff --git a/main/src/com/google/gridworks/commands/column/MoveColumnCommand.java b/main/src/com/google/gridworks/commands/column/MoveColumnCommand.java new file mode 100644 index 000000000..430d74d75 --- /dev/null +++ b/main/src/com/google/gridworks/commands/column/MoveColumnCommand.java @@ -0,0 +1,35 @@ +package com.google.gridworks.commands.column; + +import java.io.IOException; +import java.util.Properties; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.google.gridworks.commands.Command; +import com.google.gridworks.model.AbstractOperation; +import com.google.gridworks.model.Project; +import com.google.gridworks.operations.column.ColumnMoveOperation; +import com.google.gridworks.process.Process; + +public class MoveColumnCommand extends Command { + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + try { + Project project = getProject(request); + + String columnName = request.getParameter("columnName"); + int index = Integer.parseInt(request.getParameter("index")); + + AbstractOperation op = new ColumnMoveOperation(columnName, index); + Process process = op.createProcess(project, new Properties()); + + performProcessAndRespond(request, response, project, process); + } catch (Exception e) { + respondException(response, e); + } + } +} diff --git a/main/src/com/google/gridworks/model/changes/ColumnMoveChange.java b/main/src/com/google/gridworks/model/changes/ColumnMoveChange.java new file mode 100644 index 000000000..789d92c51 --- /dev/null +++ b/main/src/com/google/gridworks/model/changes/ColumnMoveChange.java @@ -0,0 +1,75 @@ +package com.google.gridworks.model.changes; + +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.Writer; +import java.util.Properties; + +import com.google.gridworks.history.Change; +import com.google.gridworks.model.Column; +import com.google.gridworks.model.Project; +import com.google.gridworks.util.Pool; + +public class ColumnMoveChange extends ColumnChange { + final protected String _columnName; + final protected int _newColumnIndex; + protected int _oldColumnIndex; + + public ColumnMoveChange(String columnName, int index) { + _columnName = columnName; + _newColumnIndex = index; + } + + public void apply(Project project) { + synchronized (project) { + _oldColumnIndex = project.columnModel.getColumnIndexByName(_columnName); + + Column column = project.columnModel.columns.remove(_oldColumnIndex); + project.columnModel.columns.add(_newColumnIndex, column); + + project.update(); + } + } + + public void revert(Project project) { + synchronized (project) { + Column column = project.columnModel.columns.remove(_newColumnIndex); + project.columnModel.columns.add(_oldColumnIndex, column); + + project.update(); + } + } + + public void save(Writer writer, Properties options) throws IOException { + writer.write("columnName="); writer.write(_columnName); writer.write('\n'); + writer.write("oldColumnIndex="); writer.write(Integer.toString(_oldColumnIndex)); writer.write('\n'); + writer.write("newColumnIndex="); writer.write(Integer.toString(_newColumnIndex)); writer.write('\n'); + writer.write("/ec/\n"); // end of change marker + } + + static public Change load(LineNumberReader reader, Pool pool) throws Exception { + String columnName = null; + int oldColumnIndex = -1; + int newColumnIndex = -1; + + String line; + while ((line = reader.readLine()) != null && !"/ec/".equals(line)) { + int equal = line.indexOf('='); + CharSequence field = line.subSequence(0, equal); + + String value = line.substring(equal + 1); + if ("oldColumnIndex".equals(field)) { + oldColumnIndex = Integer.parseInt(value); + } else if ("newColumnIndex".equals(field)) { + newColumnIndex = Integer.parseInt(value); + } else if ("columnName".equals(field)) { + columnName = value; + } + } + + ColumnMoveChange change = new ColumnMoveChange(columnName, newColumnIndex); + change._oldColumnIndex = oldColumnIndex; + + return change; + } +} diff --git a/main/src/com/google/gridworks/operations/OperationRegistry.java b/main/src/com/google/gridworks/operations/OperationRegistry.java index 0fe9cfed2..141762262 100644 --- a/main/src/com/google/gridworks/operations/OperationRegistry.java +++ b/main/src/com/google/gridworks/operations/OperationRegistry.java @@ -15,6 +15,7 @@ import com.google.gridworks.operations.cell.MultiValuedCellSplitOperation; import com.google.gridworks.operations.cell.TextTransformOperation; import com.google.gridworks.operations.cell.TransposeColumnsIntoRowsOperation; import com.google.gridworks.operations.column.ColumnAdditionOperation; +import com.google.gridworks.operations.column.ColumnMoveOperation; import com.google.gridworks.operations.column.ColumnRemovalOperation; import com.google.gridworks.operations.column.ColumnRenameOperation; import com.google.gridworks.operations.column.ColumnSplitOperation; @@ -57,6 +58,7 @@ public abstract class OperationRegistry { register("column-addition", ColumnAdditionOperation.class); register("column-removal", ColumnRemovalOperation.class); register("column-rename", ColumnRenameOperation.class); + register("column-move", ColumnMoveOperation.class); register("column-split", ColumnSplitOperation.class); register("extend-data", ExtendDataOperation.class); diff --git a/main/src/com/google/gridworks/operations/column/ColumnMoveOperation.java b/main/src/com/google/gridworks/operations/column/ColumnMoveOperation.java new file mode 100644 index 000000000..ebf68b96c --- /dev/null +++ b/main/src/com/google/gridworks/operations/column/ColumnMoveOperation.java @@ -0,0 +1,60 @@ +package com.google.gridworks.operations.column; + +import java.util.Properties; + +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONWriter; + +import com.google.gridworks.history.Change; +import com.google.gridworks.history.HistoryEntry; +import com.google.gridworks.model.AbstractOperation; +import com.google.gridworks.model.Project; +import com.google.gridworks.model.changes.ColumnMoveChange; +import com.google.gridworks.operations.OperationRegistry; + +public class ColumnMoveOperation extends AbstractOperation { + final protected String _columnName; + final protected int _index; + + static public AbstractOperation reconstruct(Project project, JSONObject obj) throws Exception { + return new ColumnMoveOperation( + obj.getString("columnName"), + obj.getInt("index") + ); + } + + public ColumnMoveOperation( + String columnName, + int index + ) { + _columnName = columnName; + _index = index; + } + + public void write(JSONWriter writer, Properties options) + throws JSONException { + + writer.object(); + writer.key("op"); writer.value(OperationRegistry.s_opClassToName.get(this.getClass())); + writer.key("description"); writer.value("Move column " + _columnName + " to position " + _index); + writer.key("columnName"); writer.value(_columnName); + writer.key("index"); writer.value(_index); + writer.endObject(); + } + + + protected String getBriefDescription(Project project) { + return "Move column " + _columnName + " to position " + _index; + } + + protected HistoryEntry createHistoryEntry(Project project, long historyEntryID) throws Exception { + if (project.columnModel.getColumnByName(_columnName) == null) { + throw new Exception("No column named " + _columnName); + } + + Change change = new ColumnMoveChange(_columnName, _index); + + return new HistoryEntry(historyEntryID, project, getBriefDescription(null), ColumnMoveOperation.this, change); + } +} diff --git a/main/webapp/modules/core/scripts/project.js b/main/webapp/modules/core/scripts/project.js index 634e743aa..e39b35a98 100644 --- a/main/webapp/modules/core/scripts/project.js +++ b/main/webapp/modules/core/scripts/project.js @@ -322,6 +322,16 @@ Gridworks.columnNameToColumn = function(columnName) { } return null; }; +Gridworks.columnNameToColumnIndex = function(columnName) { + var columns = theProject.columnModel.columns; + for (var i = 0; i < columns.length; i++) { + var column = columns[i]; + if (column.name == columnName) { + return i; + } + } + return -1; +}; Gridworks.preparePool = function(pool) { for (var id in pool.recons) { diff --git a/main/webapp/modules/core/scripts/views/data-table/data-table-column-header-ui.js b/main/webapp/modules/core/scripts/views/data-table/data-table-column-header-ui.js index 9e1231440..c1ec9b87b 100644 --- a/main/webapp/modules/core/scripts/views/data-table/data-table-column-header-ui.js +++ b/main/webapp/modules/core/scripts/views/data-table/data-table-column-header-ui.js @@ -326,6 +326,23 @@ DataTableColumnHeaderUI.prototype._createMenuForColumnHeader = function(elmt) { { label: "Remove This Column", click: function() { self._doRemoveColumn(); } + }, + {}, + { + label: "Move Column to Beginning", + click: function() { self._doMoveColumnTo(0); } + }, + { + label: "Move Column to End", + click: function() { self._doMoveColumnTo(theProject.columnModel.columns.length - 1); } + }, + { + label: "Move Column Left", + click: function() { self._doMoveColumnBy(-1); } + }, + { + label: "Move Column Right", + click: function() { self._doMoveColumnBy(1); } } ] }, @@ -934,6 +951,30 @@ DataTableColumnHeaderUI.prototype._doRenameColumn = function() { } }; +DataTableColumnHeaderUI.prototype._doMoveColumnTo = function(index) { + Gridworks.postProcess( + "move-column", + { + columnName: this._column.name, + index: index + }, + null, + { modelsChanged: true } + ); +}; + +DataTableColumnHeaderUI.prototype._doMoveColumnBy = function(change) { + Gridworks.postProcess( + "move-column", + { + columnName: this._column.name, + index: Gridworks.columnNameToColumnIndex(this._column.name) + change + }, + null, + { modelsChanged: true } + ); +}; + DataTableColumnHeaderUI.prototype._doFillDown = function() { Gridworks.postProcess( "fill-down",