SideBySide2: Add "or [x] entire file" context option
Make it easier for users to get whole file context setting by adding a checkbox next to the input field. When set the field is cleared, so now users see: Context Lines [ ] or [x] entire file There are focus problems when the user modifies the lines of context input text box and then clicks the "entire file" check mark to show the entire file. The browser first delivers the change event for the text box, and then delivers the click event on the checkmark. Debounce these by delaying update of the view by 200 milliseconds, allowing the second click event to cancel the first update and take priority, as this reflects the user intent. When entire file is checked and the user enters a number into the context box, immediately uncheck the entire file check box. When focus is lost from the context box its new value will be committed and the view will be updated. Change-Id: Ic8f8f480df3ef39115c5322516ec149c1df8f89e
This commit is contained in:
		| @@ -14,6 +14,7 @@ | ||||
|  | ||||
| package com.google.gerrit.client.diff; | ||||
|  | ||||
| import static com.google.gerrit.reviewdb.client.AccountDiffPreference.DEFAULT_CONTEXT; | ||||
| import static com.google.gerrit.reviewdb.client.AccountDiffPreference.WHOLE_FILE_CONTEXT; | ||||
| import static com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace.IGNORE_ALL_SPACE; | ||||
| import static com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace.IGNORE_NONE; | ||||
| @@ -34,13 +35,16 @@ import com.google.gwt.event.dom.client.ChangeEvent; | ||||
| import com.google.gwt.event.dom.client.ClickEvent; | ||||
| import com.google.gwt.event.dom.client.KeyDownEvent; | ||||
| import com.google.gwt.event.dom.client.KeyDownHandler; | ||||
| import com.google.gwt.event.dom.client.KeyPressEvent; | ||||
| import com.google.gwt.event.logical.shared.ValueChangeEvent; | ||||
| import com.google.gwt.resources.client.CssResource; | ||||
| import com.google.gwt.uibinder.client.UiBinder; | ||||
| import com.google.gwt.uibinder.client.UiField; | ||||
| import com.google.gwt.uibinder.client.UiHandler; | ||||
| import com.google.gwt.user.client.Timer; | ||||
| import com.google.gwt.user.client.ui.Anchor; | ||||
| import com.google.gwt.user.client.ui.Button; | ||||
| import com.google.gwt.user.client.ui.CheckBox; | ||||
| import com.google.gwt.user.client.ui.Composite; | ||||
| import com.google.gwt.user.client.ui.HTMLPanel; | ||||
| import com.google.gwt.user.client.ui.ListBox; | ||||
| @@ -62,12 +66,15 @@ class PreferencesBox extends Composite { | ||||
|   private final CodeMirror cmA; | ||||
|   private final CodeMirror cmB; | ||||
|   private DiffPreferences prefs; | ||||
|   private int contextLastValue; | ||||
|   private Timer updateContextTimer; | ||||
|  | ||||
|   @UiField Style style; | ||||
|   @UiField Anchor close; | ||||
|   @UiField ListBox ignoreWhitespace; | ||||
|   @UiField NpIntTextBox tabWidth; | ||||
|   @UiField NpIntTextBox context; | ||||
|   @UiField CheckBox contextEntireFile; | ||||
|   @UiField ToggleButton intralineDifference; | ||||
|   @UiField ToggleButton syntaxHighlighting; | ||||
|   @UiField ToggleButton whitespaceErrors; | ||||
| @@ -91,8 +98,7 @@ class PreferencesBox extends Composite { | ||||
|     super.onLoad(); | ||||
|  | ||||
|     save.setVisible(Gerrit.isSignedIn()); | ||||
|     addDomHandler( | ||||
|       new KeyDownHandler() { | ||||
|     addDomHandler(new KeyDownHandler() { | ||||
|       @Override | ||||
|       public void onKeyDown(KeyDownEvent event) { | ||||
|         if (event.getNativeKeyCode() == KEY_ESCAPE | ||||
| @@ -100,8 +106,16 @@ class PreferencesBox extends Composite { | ||||
|           close(); | ||||
|         } | ||||
|       } | ||||
|       }, | ||||
|       KeyDownEvent.getType()); | ||||
|     }, KeyDownEvent.getType()); | ||||
|     updateContextTimer = new Timer() { | ||||
|       @Override | ||||
|       public void run() { | ||||
|         if (prefs.context() == WHOLE_FILE_CONTEXT) { | ||||
|           contextEntireFile.setValue(true); | ||||
|         } | ||||
|         view.setContext(prefs.context()); | ||||
|       } | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   void set(DiffPreferences prefs) { | ||||
| @@ -129,9 +143,12 @@ class PreferencesBox extends Composite { | ||||
|     } | ||||
|  | ||||
|     if (prefs.context() == WHOLE_FILE_CONTEXT) { | ||||
|       contextLastValue = DEFAULT_CONTEXT; | ||||
|       context.setText(""); | ||||
|       contextEntireFile.setValue(true); | ||||
|     } else { | ||||
|       context.setIntValue(prefs.context()); | ||||
|       contextEntireFile.setValue(false); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -148,19 +165,48 @@ class PreferencesBox extends Composite { | ||||
|     view.setShowIntraline(prefs.intralineDifference()); | ||||
|   } | ||||
|  | ||||
|   @UiHandler("context") | ||||
|   void onContextKey(KeyPressEvent e) { | ||||
|     if (contextEntireFile.getValue()) { | ||||
|       char c = e.getCharCode(); | ||||
|       if ('0' <= c && c <= '9') { | ||||
|         contextEntireFile.setValue(false); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @UiHandler("context") | ||||
|   void onContext(ValueChangeEvent<String> e) { | ||||
|     String v = e.getValue(); | ||||
|     int c; | ||||
|     if (v != null && v.length() > 0) { | ||||
|       c = Math.min(Math.max(0, Integer.parseInt(v)), 32767); | ||||
|       contextEntireFile.setValue(false); | ||||
|     } else if (v == null || v.isEmpty()) { | ||||
|       c = WHOLE_FILE_CONTEXT; | ||||
|     } else { | ||||
|       return; | ||||
|     } | ||||
|     prefs.context(c); | ||||
|     view.setContext(prefs.context()); | ||||
|     updateContextTimer.schedule(200); | ||||
|   } | ||||
|  | ||||
|   @UiHandler("contextEntireFile") | ||||
|   void onContextEntireFile(ValueChangeEvent<Boolean> e) { | ||||
|     // If a click arrives too fast after onContext applied an update | ||||
|     // the user committed the context line update by clicking on the | ||||
|     // whole file checkmark. Drop this event, but transfer focus. | ||||
|     if (e.getValue()) { | ||||
|       contextLastValue = context.getIntValue(); | ||||
|       context.setText(""); | ||||
|       prefs.context(WHOLE_FILE_CONTEXT); | ||||
|     } else { | ||||
|       prefs.context(contextLastValue > 0 ? contextLastValue : DEFAULT_CONTEXT); | ||||
|       context.setIntValue(prefs.context()); | ||||
|       context.setFocus(true); | ||||
|       context.setSelectionRange(0, context.getText().length()); | ||||
|     } | ||||
|     updateContextTimer.schedule(200); | ||||
|   } | ||||
|  | ||||
|   @UiHandler("tabWidth") | ||||
|   | ||||
| @@ -41,8 +41,10 @@ limitations under the License. | ||||
|       -moz-border-radius: 10px; | ||||
|     } | ||||
|  | ||||
|     .dialog .box { margin: 10px; } | ||||
|     .box { margin: 10px; } | ||||
|     .box .gwt-TextBox { padding: 0; } | ||||
|     .context { vertical-align: bottom; } | ||||
|  | ||||
|     .table tr { min-height: 23px; } | ||||
|     .table th, | ||||
|     .table td { | ||||
| @@ -160,9 +162,11 @@ limitations under the License. | ||||
|       </tr> | ||||
|       <tr> | ||||
|         <th><ui:msg>Lines of Context</ui:msg></th> | ||||
|         <td><x:NpIntTextBox ui:field='context' | ||||
|         <td><ui:msg><x:NpIntTextBox ui:field='context' | ||||
|             addStyleNames='{style.context}' | ||||
|             visibleLength='4' | ||||
|             alignment='RIGHT'/></td> | ||||
|             alignment='RIGHT'/> | ||||
|           or <g:CheckBox ui:field='contextEntireFile'>entire file</g:CheckBox></ui:msg></td> | ||||
|       </tr> | ||||
|       <tr> | ||||
|         <th><ui:msg>Intraline Difference</ui:msg></th> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Shawn Pearce
					Shawn Pearce