Java tutorial
/* Copyright (C) 2014 Martin Frick (mfricke@u.arizona.edu http://softoption.us mfricke@softoption.us) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package us.softoption.proofs; /*We have a cell table of prooflines * * Jan 2013 Problem with selection model * * * * */ import java.util.Arrays; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Set; import com.google.gwt.cell.client.SafeHtmlCell; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.client.Event; import com.google.gwt.view.client.CellPreviewEvent; import com.google.gwt.view.client.DefaultSelectionEventManager; import com.google.gwt.view.client.MultiSelectionModel; public class TProofDisplayCellTable extends CellTable<TProofline> { private TProofListModel fProofListModel = new TProofListModel(); private TProofController fProofController = null; private MultiSelectionModel<TProofline> fSelectionModel = new MultiSelectionModel<TProofline>(); public TProofDisplayCellTable() { addSelectionModel(); } public TProofDisplayCellTable(TProofController itsController) { fProofController = itsController; addSelectionModel(); this.setStyleName("proofDisplay"); } public TProofDisplayCellTable(TProofListModel aModel) { fProofListModel = aModel; addSelectionModel(); this.setStyleName("proofDisplay"); } /************** Getters ************************/ TProofListModel getProofListModel() { return fProofListModel; } /************** Selection and Clicks or Touches ************************/ void addSelectionModel() { this.sinkEvents(Event.ONCLICK); //but we want click to toggle selection not require command click for multiple this.addCellPreviewHandler(new CellPreviewEvent.Handler<TProofline>() { public void onCellPreview(CellPreviewEvent<TProofline> event) { String type = event.getNativeEvent().getType(); if (type.equals("click")) { TProofline value = event.getValue(); handleClick(value); event.setCanceled(true); // Window.alert("CLICKED " + value.fLineno); DEBUG } } }); this.setSelectionModel(fSelectionModel, DefaultSelectionEventManager.<TProofline>createCheckboxManager()); /* final Handler<TProofline> selectionEventManager = DefaultSelectionEventManager.createCheckboxManager(); this.setSelectionModel(fSelectionModel,selectionEventManager); Jan 2013 */ /*Google sample code * * // Add a selection model so we can select cells. final SelectionModel<ContactInfo> selectionModel = new MultiSelectionModel<ContactInfo>( ContactDatabase.ContactInfo.KEY_PROVIDER); cellTable.setSelectionModel(selectionModel, DefaultSelectionEventManager.<ContactInfo> createCheckboxManager()); */ // We want multiple selection // final MultiSelectionModel<TProofline> selectionModel = new MultiSelectionModel<TProofline>(); /* this.setSelectionModel(fSelectionModel); fSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { public void onSelectionChange(SelectionChangeEvent event) { Set <TProofline> selected = fSelectionModel.getSelectedSet(); if (selected != null) { Window.alert("You selected: " + selected.size()); } } }); */ /* this.addCellPreviewHandler(new CellPreviewEvent.Handler<TProofline>() { public void onCellPreview(CellPreviewEvent<TProofline> event) { String type = event.getNativeEvent().getType(); if (type.equals("click")) { TProofline value=event.getValue(); final Boolean state = !event.getDisplay().getSelectionModel().isSelected(value); event.getDisplay().getSelectionModel().setSelected(value, state); event.setCanceled(true); Window.alert("CLICKED"); } } }); */ /* this.addCellPreviewHandler(new Handler<T>() { @Override public void onCellPreview(final CellPreviewEvent<T> event) { if (BrowserEvents.CLICK.equals(event.getNativeEvent().getType())) { final T value = event.getValue(); final Boolean state = !event.getDisplay().getSelectionModel().isSelected(value); event.getDisplay().getSelectionModel().setSelected(value, state); event.setCanceled(true); } } }); */ } void handleClick(TProofline clickedLine) { // based on class SynchronizeSelections implements ListSelectionListener in TProofListView /* * * //this needs to unselect unselectable lines, and synchronize lines which are selected between //the prooflines in the data model and those in the celltable * * */ /* ignore null and blanklines */ if (clickedLine == null || clickedLine.fBlankline) // ignore blanklines return; /*get its formula*/ String formulaStr = fProofController.fParser.writeFormulaToString(clickedLine.fFormula); /* not null but using input pane */ if (fProofController.usingInputPane()) { // are using input panel, so touch to load if (!"?".equals(formulaStr)) fProofController.display(formulaStr); return; } /* not null, no input pane but on ? */ if ("?".equals(formulaStr) //changing goals && (!fProofController.usingInputPane()) && // don't change goals in the middle of something else (clickedLine != (fProofListModel.getTailFirstLine()))) //already at tqil no chqnge needed { fProofListModel.changeGoals(clickedLine); fProofController.bugAlert("Advisory: Changing goals.", "Notice that you have started to work on a different goal."); return; } /* not null, normal case */ //Feb152013 if ((!clickedLine.fSelectable && // can't be this !clickedLine.fSubProofSelectable)) //can't be that { fSelectionModel.setSelected(clickedLine, false); //unselect it return; } final Boolean alreadySelected = fSelectionModel.isSelected(clickedLine); /* change Feb 15 if (alreadySelected && //apparently selected (!clickedLine.fSelectable && // can't be this !clickedLine.fSubProofSelectable )) //can't be that { fSelectionModel.setSelected(clickedLine, false); //unselect it return; } */ /*all 'odd' cqses covered, just toggle it */ fSelectionModel.setSelected(clickedLine, !alreadySelected); } void clearSelections() { if (fSelectionModel != null) fSelectionModel.clear(); } /*************************** Saving and Opening Files, Beans *************************/ public TProofListModel getModel() { return fProofListModel; } public void setModel(TProofListModel aModel) { fProofListModel = aModel; } public TProofController getController() { return fProofController; } public void setController(TProofController aController) { fProofController = aController; } /* * * http://stackoverflow.com/questions/7854147/gwt-clickabletextcell * Column<DataType, String> myIntegerColumn = new Column<DataType, String>(new ClickableTextCell()); myIntegerColumn.setFieldUpdater(new FieldUpdater<DataType, String>(){ @Override public void update(int index, DataType object, String value){ // execute code that reacts to a click on this hot spot } }); */ public void synchronizeViewToData() { /* A proof looks like 1 | F^G Ass 2 || H Ass 3 || F 1 ^E now, a line (row) on its own is fine, we can use one column for the line number, then one each for the vertical lines, the formula, and the justification. Conceptually, the line numbers are col 1, the vertical lines are subcolumns of col 2, the formula is col 3, and the justification col 4. But, if we wanted to combine several lines into a table we have the problem that the different rows might have a different number of columns. But we know If this method is called with a (max) numberOfColumns, then we can insert a colspan if needed. The colspan needs to go with the formula (ie with F^G in line 1), we are looking for left justification. Now, some proofs start with a headlevel of -1, others with a headlevel of 0 (that information is on the line itself). Then the parameter tells us the maximum nesting. So the number of columns in the table as a whole is 4 + maxSubProofLevel. So, any particular line has to look at the difference between its level and the headlevel. It that is maxSubProoflevel no colspan is needed. If it is one less than maxSubProoflevel a colspan of 2 is needed ie colspan = maxSubProoflevel - difference +1 (and colspan has to be greater than 1 to matter) */ if (fProofListModel != null) { //updating display from the model //empty old int presentCols = this.getColumnCount(); for (int i = 0; i < presentCols; i++) this.removeColumn(presentCols - i - 1); //prep new int rows = fProofListModel.getRowCount(); int cols = fProofListModel.getColumnCount(); List<TProofline> rowList = fProofListModel.proofAsProoflines(); //this.setVisibleRangeAndClearData(new Range(0,0),true); this.setRowCount(0, true); //belt and braces //this.se // Create a value updater that will be called when the value in a cell // changes. // ValueUpdater<String> valueUpdater = new ValueUpdater<String>() { // public void update(String newValue) { // Window.alert("You typed: " + newValue); // } // }; // Add the value updater to the cellList. // this.setUpdater(valueUpdater); this.setRowCount(rows, true); // Add a text column to show the line number /* TextColumn<TProofline> nameColumn = new TextColumn<TProofline>() { @Override public String getValue(TProofline object) { return (object.firstColumnGWT()); } }; this.addColumn(nameColumn, "LineNo"); */ // Column<TProofline,String> aColumn=new Column<TProofline,String>(); /* Column<TProofline, String> editableColumn = new Column<TProofline, String>( new ClickableTextCell() /* (Cell)(new TProofCustomCell())*/ /*) { @Override public String getValue(TProofline parameter) { return parameter.firstColumnGWT(); } }; this.addColumn(editableColumn /*,"LineNo"); */ /****** experiment Jan 18 2013 *****/ /* final int maxSubProofLevel = fProofListModel.maxSubProofLevel(); final SafeHtmlCell lineNoCell = new SafeHtmlCell(); final SafeHtmlCell vertLinesCell = new SafeHtmlCell(); final SafeHtmlCell formulaCell = new SafeHtmlCell(); final SafeHtmlCell justificationCell = new SafeHtmlCell(); Column<TProofline, SafeHtml> safeColumn1 = new Column<TProofline, SafeHtml>( lineNoCell) { @Override public SafeHtml getValue(TProofline parameter) { SafeHtmlBuilder sb = new SafeHtmlBuilder(); sb.appendHtmlConstant(parameter.firstColumnGWT()); return sb.toSafeHtml() ; } }; this.addColumn(safeColumn1); Column<TProofline, SafeHtml> safeColumn2 = new Column<TProofline, SafeHtml>( vertLinesCell) { @Override public SafeHtml getValue(TProofline parameter) { SafeHtmlBuilder sb = new SafeHtmlBuilder(); sb.appendHtmlConstant(parameter.secondColumnGWT()); return sb.toSafeHtml() ; } }; this.addColumn(safeColumn2); Column<TProofline, SafeHtml> safeColumn3 = new Column<TProofline, SafeHtml>( formulaCell) { @Override public SafeHtml getValue(TProofline parameter) { SafeHtmlBuilder sb = new SafeHtmlBuilder(); sb.appendHtmlConstant(parameter.thirdColumnGWT(maxSubProofLevel)); return sb.toSafeHtml() ; } }; this.addColumn(safeColumn3); Column<TProofline, SafeHtml> safeColumn4 = new Column<TProofline, SafeHtml>( justificationCell) { @Override public SafeHtml getValue(TProofline parameter) { SafeHtmlBuilder sb = new SafeHtmlBuilder(); sb.appendHtmlConstant(parameter.fourthColumnGWT()); return sb.toSafeHtml() ; } }; this.addColumn(safeColumn4); this.setRowData(rowList); //now we want to set column widths this.setWidth("100%", true); //fixed layout this.setColumnWidth(safeColumn1, 36.0, Unit.PX); this.setColumnWidth(safeColumn2, 10.0, Unit.PCT); this.setColumnWidth(safeColumn3, 70.0, Unit.PCT); this.setColumnWidth(safeColumn4, 20.0, Unit.PCT); */ /******************/ /****** experiment Feb 2013 *****/ /*we really want three columns, the line number, the vert lines and formula in one, and the justification*/ final int maxSubProofLevel = fProofListModel.maxSubProofLevel(); final SafeHtmlCell lineNoCell = new SafeHtmlCell(); final SafeHtmlCell vertLinesAndFormulaCell = new SafeHtmlCell(); // final SafeHtmlCell formulaCell = new SafeHtmlCell(); final SafeHtmlCell justificationCell = new SafeHtmlCell(); Column<TProofline, SafeHtml> safeColumn1 = new Column<TProofline, SafeHtml>(lineNoCell) { @Override public SafeHtml getValue(TProofline parameter) { SafeHtmlBuilder sb = new SafeHtmlBuilder(); sb.appendHtmlConstant(parameter.firstColumnGWT()); return sb.toSafeHtml(); } }; this.addColumn(safeColumn1 /*,"Line No"*/); Column<TProofline, SafeHtml> safeColumn2 = new Column<TProofline, SafeHtml>(vertLinesAndFormulaCell) { @Override public SafeHtml getValue(TProofline parameter) { SafeHtmlBuilder sb = new SafeHtmlBuilder(); sb.appendHtmlConstant(parameter.secondAndThirdColumnGWT(maxSubProofLevel)); return sb.toSafeHtml(); } }; this.addColumn(safeColumn2 /*,"Vert Lines" and formula*/); Column<TProofline, SafeHtml> safeColumn3 = new Column<TProofline, SafeHtml>(justificationCell) { @Override public SafeHtml getValue(TProofline parameter) { SafeHtmlBuilder sb = new SafeHtmlBuilder(); sb.appendHtmlConstant(parameter.fourthColumnGWT()); return sb.toSafeHtml(); } }; this.addColumn(safeColumn3 /*,"Justification"*/); this.setRowData(rowList); //now we want to set column widths this.setWidth("100%", true); //fixed layout this.setColumnWidth(safeColumn1, 36.0, Unit.PX); //line no this.setColumnWidth(safeColumn2, 100.0, Unit.PCT); // vert lines and formula this.setColumnWidth(safeColumn3, 100.0, Unit.PX); // justification /******************/ } } // http://google-web-toolkit.googlecode.com/svn/javadoc/2.1/com/google/gwt/user/cellview/client/CellTable.html /***********************************************************************/ /***************************Selection ********************************************/ void clearSelection() { fSelectionModel.clear(); //(TO DO) apparently done Jan 2013 } //TO DO //public boolean oneSelected(){return true;} public TProofline oneSelected() { TProofline[] selection = exactlyNLinesSelected(1); if ((selection != null) && (selection.length == 1)) return selection[0]; else return null; } public int totalSelected() { Set<TProofline> selections = fSelectionModel.getSelectedSet(); return selections.size(); } public TProofline[] exactlyNLinesSelected(int n) { // exactly n, selected and selectable, some selected lines are not, for those indicating subproofs //maybe not work for 0? int numFound = 0; //int []selections = getSelectedRows(); // TO DO getSelectedRows(); Set<TProofline> selections = fSelectionModel.getSelectedSet(); int numSelections = selections.size(); if (numSelections < n) //at least n needed return null; else { TProofline[] returnArray = new TProofline[n]; TProofline selectedLine; TProofline[] selArray = new TProofline[numSelections]; selArray = selections.toArray(selArray); for (int i = 0; i < numSelections; i++) { selectedLine = selArray[i]; //TO DO (TProofline)getValueAt(selections[i],TProofTableModel.fProofColIndex); //2 columns //selectedLine = (TProofline) selections[i]; if (selectedLine.fSelectable) { if (numFound < n) { returnArray[numFound] = selectedLine; numFound += 1; } else return null; } } if (numFound == n) { Arrays.sort(returnArray, new prooflineComparator()); return returnArray; } else return null; } } public TProofline[][] nSubProofsSelected(int n) { // exactly n proofs selected /*{The condition is that it is selected and the nextline is a blankline indicating eo subproof} However, we don't worry about the blankline because another routine resetSelectables? checks it and sets the field fSubProofSelectable*/ /* Each subproof has to have a head and a tail, so we will return an array of two element arrays*/ TProofline head = null, tail = null, searchline = null; int numFound = 0; Set<TProofline> selections = fSelectionModel.getSelectedSet(); int numSelections = selections.size(); if (numSelections < n) //must have at least n, can have more if there are ordinary selections return null; else { TProofline[][] returnArray = new TProofline[n][2]; TProofline selectedLine; TProofline[] selArray = new TProofline[numSelections]; selArray = selections.toArray(selArray); for (int i = 0; (i < numSelections); i++) { selectedLine = selArray[i]; if (selectedLine.fSubProofSelectable) { // may be one tail = selectedLine; head = null; Iterator iter = fProofListModel.getHead().iterator(); while (iter.hasNext()) { searchline = (TProofline) iter.next(); if ((searchline.fJustification.equals(TProofController.fAssJustification)) && (searchline.fSubprooflevel == tail.fSubprooflevel) && (searchline.fLineno <= tail.fLineno)) head = searchline; // looking for last one } if (head != null) { // finished while loop and we have found one if (numFound >= n) return null; // there are too many, bale else { returnArray[numFound][0] = head; returnArray[numFound][1] = tail; numFound += 1; } } } } if (numFound == n) return returnArray; else return null; } } class prooflineComparator implements Comparator<TProofline> { // Comparator interface requires defining compare method. public int compare(TProofline lineA, TProofline lineB) { //... Sort directories before files, // otherwise alphabetical ignoring case. if (lineA.fLineno > lineB.fLineno) return 1; else if (lineA.fLineno < lineB.fLineno) return -1; else return -1; } } }