In progress: [Issue 104] Update "Next Id" comment when generating a the
tag number of a field or literal

Working on preference page for patterns.
diff --git a/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties b/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
index 273a9fe..66f116e 100644
--- a/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
+++ b/com.google.eclipse.protobuf.ui/OSGI-INF/l10n/bundle.properties
@@ -9,6 +9,7 @@
 page.name.3 = Import Paths
 page.name.4 = Editor
 page.name.5 = Save Actions
+page.name.6 = Tag Number Patterns
 keyword.label = Protocol Buffer
 command.description = Trigger expensive validation
 command.name = Validate
diff --git a/com.google.eclipse.protobuf.ui/plugin.xml b/com.google.eclipse.protobuf.ui/plugin.xml
index 6fdc940..667dbd2 100644
--- a/com.google.eclipse.protobuf.ui/plugin.xml
+++ b/com.google.eclipse.protobuf.ui/plugin.xml
@@ -74,7 +74,12 @@
     </page>
     <page category="com.google.eclipse.protobuf.ui.preferences.pages.editor"
       class="com.google.eclipse.protobuf.ui.ProtobufExecutableExtensionFactory:com.google.eclipse.protobuf.ui.preferences.pages.editor.save.SaveActionsPreferencePage"
-      id="com.google.eclipse.protobuf.ui.preferences.pages.editor" name="%page.name.5">
+      id="com.google.eclipse.protobuf.ui.preferences.pages.editor.save.SaveActionsPreferencePage" name="%page.name.5">
+      <keywordReference id="com.google.eclipse.protobuf.ui.keyword_Protobuf" />
+    </page>
+    <page category="com.google.eclipse.protobuf.ui.preferences.pages.editor"
+      class="com.google.eclipse.protobuf.ui.ProtobufExecutableExtensionFactory:com.google.eclipse.protobuf.ui.preferences.pages.editor.tagpatterns.TagPatternsPreferencePage"
+      id="com.google.eclipse.protobuf.ui.preferences.pages.editor.tagpatterns.TagPatternsPreferencePage" name="%page.name.6">
       <keywordReference id="com.google.eclipse.protobuf.ui.keyword_Protobuf" />
     </page>
   </extension>
@@ -194,28 +199,22 @@
           </adapt>
        </enabledWhen>
     </page>
-    <page
-          category="com.google.eclipse.protobuf.Protobuf"
+    <page category="com.google.eclipse.protobuf.Protobuf"
           class="com.google.eclipse.protobuf.ui.ProtobufExecutableExtensionFactory:com.google.eclipse.protobuf.ui.preferences.pages.compiler.CompilerPreferencePage"
           id="com.google.eclipse.protobuf.ui.properties.compiler.PropertyPage"
           name="%page.name.2"
           selectionFilter="single">
        <enabledWhen>
-          <adapt
-                type="org.eclipse.core.resources.IProject">
-          </adapt>
+          <adapt type="org.eclipse.core.resources.IProject" />
        </enabledWhen>
     </page>
-    <page
-          category="com.google.eclipse.protobuf.Protobuf"
+    <page category="com.google.eclipse.protobuf.Protobuf"
           class="com.google.eclipse.protobuf.ui.ProtobufExecutableExtensionFactory:com.google.eclipse.protobuf.ui.preferences.pages.paths.PathsPreferencePage"
           id="com.google.eclipse.protobuf.ui.properties.paths.PropertyPage"
           name="%page.name.3"
           selectionFilter="single">
        <enabledWhen>
-          <adapt
-                type="org.eclipse.core.resources.IProject">
-          </adapt>
+          <adapt type="org.eclipse.core.resources.IProject" />
        </enabledWhen>
     </page>
   </extension>
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
index 444632d..957a9c5 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/commands/SmartSemicolonHandler.java
@@ -9,6 +9,7 @@
 package com.google.eclipse.protobuf.ui.commands;
 
 import static com.google.eclipse.protobuf.grammar.CommonKeyword.SEMICOLON;
+import static com.google.eclipse.protobuf.junit.util.SystemProperties.lineSeparator;
 import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.*;
 
 import com.google.eclipse.protobuf.protobuf.*;
@@ -17,6 +18,7 @@
 import com.google.inject.Inject;
 
 import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.swt.custom.StyledText;
 import org.eclipse.xtext.*;
 import org.eclipse.xtext.nodemodel.INode;
@@ -24,9 +26,12 @@
 import org.eclipse.xtext.ui.editor.XtextEditor;
 import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext;
 import org.eclipse.xtext.ui.editor.contentassist.antlr.ParserBasedContentAssistContextFactory;
+import org.eclipse.xtext.ui.editor.model.IXtextDocument;
 import org.eclipse.xtext.util.concurrent.IUnitOfWork;
 import org.eclipse.xtext.validation.IConcreteSyntaxValidator.InvalidConcreteSyntaxException;
 
+import java.util.regex.Pattern;
+
 /**
  * Inserts a semicolon at the end of a line, regardless of the current position of the caret in the editor. If the
  * line of code being edited is a property or enum literal and if it does not have an index yet, this handler will
@@ -36,10 +41,11 @@
  */
 public class SmartSemicolonHandler extends SmartInsertHandler {
 
-  @Inject private ParserBasedContentAssistContextFactory contextFactory;
+  @Inject private CommentNodesFinder commentNodesFinder;
   @Inject private Fields fields;
   @Inject private Literals literals;
   @Inject private ModelNodes nodes;
+  @Inject private ParserBasedContentAssistContextFactory contextFactory;
 
   private final String semicolon = SEMICOLON.toString();
 
@@ -61,7 +67,8 @@
   
   private ContentToInsert newContent(final XtextEditor editor, final StyledText styledText, final String line) {
     try {
-      return editor.getDocument().modify(new IUnitOfWork<ContentToInsert, XtextResource>() {
+      final IXtextDocument document = editor.getDocument();
+      return document.modify(new IUnitOfWork<ContentToInsert, XtextResource>() {
         public ContentToInsert exec(XtextResource state) {
           int offset = styledText.getCaretOffset();
           ContentAssistContext[] context = contextFactory.create(editor.getInternalSourceViewer(), offset, state);
@@ -79,6 +86,7 @@
               if (content.equals(ContentToInsert.NONE)) {
                 int index = literals.calculateIndexOf(literal);
                 literal.setIndex(index);
+                updateIndexInCommentOfParent(literal, index, document);
               }
               return content;
             }
@@ -88,6 +96,7 @@
               if (content.equals(ContentToInsert.NONE)) {
                 int index = fields.calculateTagNumberOf(property);
                 property.setIndex(index);
+                updateIndexInCommentOfParent(property, index, document);
               }
               return content;
             }
@@ -98,7 +107,7 @@
     } catch (InvalidConcreteSyntaxException e) {}
     return ContentToInsert.NONE;
   }
-
+  
   private boolean isCommentOrString(INode currentNode) {
     return nodes.wasCreatedByAnyComment(currentNode) || wasCreatedByString(currentNode);
   }
@@ -126,6 +135,21 @@
     return (indexNode != null) ? new ContentToInsert(semicolon, Location.END) : ContentToInsert.NONE;
   }
   
+  private void updateIndexInCommentOfParent(EObject o, int index, IXtextDocument document) {
+//    EObject parent = o.eContainer();
+//    if (parent == null) return;
+//    INode node = commentNodesFinder.matchingCommentNode(parent, Pattern.compile("// Next Id: [0-9]"));
+//    if (node == null) {
+//      System.out.println("No matching node");
+//      return;
+//    }
+//    try {
+//      document.replace(node.getOffset(), node.getText().length(), "// Next Id: " + (index + 1) + lineSeparator());
+//    } catch (BadLocationException e) {
+//      e.printStackTrace();
+//    }
+  }
+  
   private static class ContentToInsert {
     final String value;
     final Location location;
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferencePage.java
index 9649ea5..d193b0c 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/compiler/CompilerPreferencePage.java
@@ -267,7 +267,6 @@
     codeGenerationEditor.codeGenerationSettings(codeGenerationSettings);
   }
 
-  /** {@inheritDoc} */
   @Override protected void onProjectSettingsActivation(boolean active) {
     enableProjectSpecificOptions(active);
     enableCompilerOptions(isEnabledAndSelected(btnCompileProtoFiles));
@@ -327,7 +326,6 @@
     btnRefreshOutputDirectory.setEnabled(isEnabled);
   }
 
-  /** {@inheritDoc} */
   @Override protected String preferencePageId() {
     return PREFERENCE_PAGE_ID;
   }
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/EditorPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/EditorPreferencePage.java
index 9a94b41..13a3cca 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/EditorPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/EditorPreferencePage.java
@@ -30,8 +30,8 @@
     contents.setLayout(new GridLayout(1, false));
 
     Link link = new Link(contents, SWT.NONE);
-    GridData gridData= new GridData(SWT.FILL, SWT.BEGINNING, true, false);
-    gridData.widthHint= 150; // only expand further if anyone else requires it
+    GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
+    gridData.widthHint = 150; // only expand further if anyone else requires it
     link.setLayoutData(gridData);
     link.setText(header);
     link.addListener(SWT.Selection, new Listener() {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/save/SaveActionsPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/save/SaveActionsPreferencePage.java
index 2b9c858..4116204 100644
--- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/save/SaveActionsPreferencePage.java
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/save/SaveActionsPreferencePage.java
@@ -20,6 +20,7 @@
 import org.eclipse.ui.*;
 import org.eclipse.xtext.ui.editor.preferences.IPreferenceStoreAccess;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
 
 /**
  * "Save Actions" preference page.
@@ -27,8 +28,6 @@
  * @author alruiz@google.com (Alex Ruiz)
  */
 public class SaveActionsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
-  public SaveActionsPreferencePage() {
-  }
 
   @Inject private IPreferenceStoreAccess preferenceStoreAccess;
 
@@ -43,6 +42,7 @@
     Composite contents = new Composite(parent, NONE);
     contents.setLayout(new GridLayout(1, false));
     btnRemoveTrailingwhitespace = new Button(contents, SWT.CHECK);
+    btnRemoveTrailingwhitespace.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
     btnRemoveTrailingwhitespace.setText("Remove trailing &whitespace");
     setUpBinding();
     preferenceBinder.applyValues();
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/tagpatterns/TagPatternsPreferencePage.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/tagpatterns/TagPatternsPreferencePage.java
new file mode 100644
index 0000000..6e40ca6
--- /dev/null
+++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/preferences/pages/editor/tagpatterns/TagPatternsPreferencePage.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011 Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package com.google.eclipse.protobuf.ui.preferences.pages.editor.tagpatterns;
+
+import com.google.eclipse.protobuf.ui.preferences.BooleanPreference;
+import com.google.eclipse.protobuf.ui.preferences.binding.PreferenceBinder;
+import com.google.eclipse.protobuf.ui.preferences.pages.PreferenceAndPropertyPage;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.jface.viewers.ListViewer;
+
+/**
+ * Preference page where users can specify the patterns to use to match comments where "the next id" is being tracked.
+ * 
+ * @author alruiz@google.com (Alex Ruiz)
+ */
+public class TagPatternsPreferencePage extends PreferenceAndPropertyPage {
+  
+  private List lstPaths;
+  private Button btnAdd;
+
+  @Override protected void doCreateContents(Composite parent) {
+    Label lblDescription = new Label(parent, SWT.NONE);
+    GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
+    // gridData.horizontalSpan = 3;
+    gridData.widthHint = 150; // only expand further if anyone else requires it
+    lblDescription.setLayoutData(gridData);
+    lblDescription.setText("Patterns to match the comments that track the next available tag number in message fields and enum literals.");
+    
+    ListViewer lstVwrPaths = new ListViewer(parent, SWT.BORDER | SWT.V_SCROLL);
+    lstPaths = lstVwrPaths.getList();
+    gridData = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+    gridData.heightHint = 121;
+    lstPaths.setLayoutData(gridData);
+    
+    Composite composite = new Composite(parent, SWT.NONE);
+    composite.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false, 1, 1));
+    composite.setLayout(new GridLayout(1, false));
+    
+    btnAdd = new Button(composite, SWT.NONE);
+    btnAdd.setSize(88, 29);
+    btnAdd.setText("&Add");
+  }
+
+  @Override protected BooleanPreference enableProjectSettingsPreference(IPreferenceStore store) {
+    // TODO(alruiz): Auto-generated method stub
+    return null;
+  }
+
+  @Override protected void setupBinding(PreferenceBinder preferenceBinder) {
+    // TODO(alruiz): Auto-generated method stub
+
+  }
+
+  @Override protected void onProjectSettingsActivation(boolean projectSettingsActive) {
+    // TODO(alruiz): Auto-generated method stub
+
+  }
+
+  @Override protected String preferencePageId() {
+    // TODO(alruiz): Auto-generated method stub
+    return null;
+  }
+}