]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/assist/StyledTextContentAdapter.java
Merge "Fixed StyledtextContentAdapter to overwrite existing content properly"
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / assist / StyledTextContentAdapter.java
index 35ded0599ced613adfcdbeb4378630941c389b42..899b9e731dd7800d7447e32988abbf588120edae 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2008 Mateusz Matela and others.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     Mateusz Matela <mateusz.matela@gmail.com> -  Make StyledText work with ContentAssistCommandAdapter - https://bugs.eclipse.org/bugs/show_bug.cgi?id=246388\r
- *******************************************************************************/\r
-package org.simantics.scl.ui.assist;\r
-\r
-import org.eclipse.jface.fieldassist.IControlContentAdapter;\r
-import org.eclipse.jface.fieldassist.IControlContentAdapter2;\r
-import org.eclipse.swt.custom.StyledText;\r
-import org.eclipse.swt.graphics.Point;\r
-import org.eclipse.swt.graphics.Rectangle;\r
-import org.eclipse.swt.widgets.Control;\r
-\r
-/**\r
- * An {@link IControlContentAdapter} for {@link org.eclipse.swt.custom.StyledText}. This is\r
- * a convenience class for easily creating a {@link ContentProposalAdapter} for text fields.\r
- * \r
- * @since 3.5\r
- */\r
-public class StyledTextContentAdapter implements IControlContentAdapter, IControlContentAdapter2 {\r
-       /*\r
-        * (non-Javadoc)\r
-        * \r
-        * @see\r
-        * org.eclipse.jface.fieldassist.IControlContentAdapter#getControlContents(org.eclipse\r
-        * .swt.widgets.Control)\r
-        */\r
-       public String getControlContents(Control control) {\r
-               return ((StyledText)control).getText();\r
-       }\r
-\r
-       /*\r
-        * (non-Javadoc)\r
-        * \r
-        * @see\r
-        * org.eclipse.jface.fieldassist.IControlContentAdapter#getCursorPosition(org.eclipse\r
-        * .swt.widgets.Control)\r
-        */\r
-       public int getCursorPosition(Control control) {\r
-               return ((StyledText)control).getCaretOffset();\r
-       }\r
-\r
-       /*\r
-        * (non-Javadoc)\r
-        * \r
-        * @see\r
-        * org.eclipse.jface.fieldassist.IControlContentAdapter#getInsertionBounds(org.eclipse\r
-        * .swt.widgets.Control)\r
-        */\r
-       public Rectangle getInsertionBounds(Control control) {\r
-               StyledText text= (StyledText)control;\r
-               Point caretOrigin= text.getLocationAtOffset(text.getCaretOffset());\r
-               return new Rectangle(caretOrigin.x + text.getClientArea().x, caretOrigin.y + text.getClientArea().y + 3, 1, text.getLineHeight());\r
-       }\r
-\r
-       /*\r
-        * (non-Javadoc)\r
-        * \r
-        * @see\r
-        * org.eclipse.jface.fieldassist.IControlContentAdapter#insertControlContents(org.eclipse\r
-        * .swt.widgets.Control, java.lang.String, int)\r
-        */\r
-       public void insertControlContents(Control control, String contents, int cursorPosition) {\r
-               StyledText text = ((StyledText)control);\r
-               cursorPosition = Math.min(cursorPosition, contents.length());\r
-               int caretEndRange = text.getCaretOffset();\r
-               String currentText = text.getText();\r
-               \r
-               int offset = caretEndRange;\r
-        int length = currentText.length();\r
-        while (--offset >= 0 && (Character.isJavaIdentifierPart(currentText.charAt(offset)) && !Character.isWhitespace(currentText.charAt(offset))))\r
-            length--;\r
-               \r
-               int nameSpaceBeginRange = currentText.lastIndexOf(".", caretEndRange - 1);\r
-               if (nameSpaceBeginRange > length)\r
-                   length = nameSpaceBeginRange;\r
-               int endRange = currentText.length();\r
-               if (caretEndRange < endRange)\r
-                   endRange = caretEndRange;\r
-               text.setSelection(length, endRange);\r
-               text.insert(contents);\r
-               // calculate the initial count of letters that was typed when the proposal was accepted to insert the caret\r
-               // at the right position\r
-               int proposalFirstLettersCount = endRange - (length);\r
-               text.setCaretOffset(caretEndRange + cursorPosition - proposalFirstLettersCount);\r
-       }\r
-\r
-       /*\r
-        * (non-Javadoc)\r
-        * \r
-        * @see\r
-        * org.eclipse.jface.fieldassist.IControlContentAdapter#setControlContents(org.eclipse\r
-        * .swt.widgets.Control, java.lang.String, int)\r
-        */\r
-       public void setControlContents(Control control, String contents, int cursorPosition) {\r
-               ((StyledText)control).setText(contents);\r
-               ((StyledText)control).setCaretOffset(cursorPosition);\r
-       }\r
-\r
-       /*\r
-        * (non-Javadoc)\r
-        * \r
-        * @see\r
-        * org.eclipse.jface.fieldassist.IControlContentAdapter#setCursorPosition(org.eclipse\r
-        * .swt.widgets.Control, int)\r
-        */\r
-       public void setCursorPosition(Control control, int index) {\r
-               ((StyledText)control).setCaretOffset(index);\r
-       }\r
-\r
-       /*\r
-        * (non-Javadoc)\r
-        * \r
-        * @see\r
-        * org.eclipse.jface.fieldassist.IControlContentAdapter2#getSelection(org.eclipse.swt\r
-        * .widgets.Control)\r
-        */\r
-       public Point getSelection(Control control) {\r
-               return ((StyledText)control).getSelection();\r
-       }\r
-\r
-       /*\r
-        * (non-Javadoc)\r
-        * \r
-        * @see\r
-        * org.eclipse.jface.fieldassist.IControlContentAdapter2#setSelection(org.eclipse.swt\r
-        * .widgets.Control, org.eclipse.swt.graphics.Point)\r
-        */\r
-       public void setSelection(Control control, Point range) {\r
-               ((StyledText)control).setSelection(range);\r
-       }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2008 Mateusz Matela and others.
+ * 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
+ *
+ * Contributors:
+ *     Mateusz Matela <mateusz.matela@gmail.com> -  Make StyledText work with ContentAssistCommandAdapter - https://bugs.eclipse.org/bugs/show_bug.cgi?id=246388
+ *******************************************************************************/
+package org.simantics.scl.ui.assist;
+
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
+import org.eclipse.jface.fieldassist.IControlContentAdapter;
+import org.eclipse.jface.fieldassist.IControlContentAdapter2;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * An {@link IControlContentAdapter} for {@link org.eclipse.swt.custom.StyledText}. This is
+ * a convenience class for easily creating a {@link ContentProposalAdapter} for text fields.
+ * 
+ * @since 3.5
+ */
+public class StyledTextContentAdapter implements IControlContentAdapter, IControlContentAdapter2 {
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.jface.fieldassist.IControlContentAdapter#getControlContents(org.eclipse
+        * .swt.widgets.Control)
+        */
+       public String getControlContents(Control control) {
+               return ((StyledText)control).getText();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.jface.fieldassist.IControlContentAdapter#getCursorPosition(org.eclipse
+        * .swt.widgets.Control)
+        */
+       public int getCursorPosition(Control control) {
+               return ((StyledText)control).getCaretOffset();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.jface.fieldassist.IControlContentAdapter#getInsertionBounds(org.eclipse
+        * .swt.widgets.Control)
+        */
+       public Rectangle getInsertionBounds(Control control) {
+               StyledText text= (StyledText)control;
+               Point caretOrigin= text.getLocationAtOffset(text.getCaretOffset());
+               return new Rectangle(caretOrigin.x + text.getClientArea().x, caretOrigin.y + text.getClientArea().y + 3, 1, text.getLineHeight());
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.jface.fieldassist.IControlContentAdapter#insertControlContents(org.eclipse
+        * .swt.widgets.Control, java.lang.String, int)
+        */
+       public void insertControlContents(Control control, String contents, int cursorPosition) {
+               StyledText text = ((StyledText)control);
+               cursorPosition = Math.min(cursorPosition, contents.length());
+
+               int caretOffset = text.getCaretOffset();
+               String currentText = text.getText();
+               int replacementOffset = findPrefixMatchOffset(currentText, caretOffset, contents);
+
+//             System.out.println("text: " + currentText);
+//             System.out.println("proposal to fill: " + contents);
+//             System.out.format("longest match of proposed contents found from text @ offset %d: \"%s[%s]%s\"%n",
+//                             replacementOffset,
+//                             currentText.substring(0, replacementOffset),
+//                             currentText.substring(replacementOffset, caretOffset),
+//                             currentText.substring(caretOffset));
+
+               // The text between [replaceOffset, caretOffset) will be replaced with `contents`
+               text.setSelection(replacementOffset, caretOffset);
+               text.insert(contents);
+               text.setSelection(replacementOffset + contents.length());
+       }
+
+       /**
+        * Find offset of longest prefix match of <code>match</code> in
+        * <code>text</code> ending at offset <code>endOffset</code>.
+        * 
+        * Example:
+        * <pre>
+        * ...  res (=text)
+        * resource (=match)
+        *  resourc
+        *   resour
+        *    resou
+        *     reso
+        *      res match! return endOffset - 3
+        * </pre>
+        * 
+        * @param text the text from which to find the match
+        * @param endOffset endOffset until which to search for the longest match
+        * @param match the text to prefix-match
+        * @return
+        */
+       private static int findPrefixMatchOffset(String text, int endOffset, String match) {
+               for (int i = match.length(); i >= 0; --i) {
+                       if (text.regionMatches(true, endOffset - i, match, 0, i))
+                               return endOffset - i;
+               }
+               return 0;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.jface.fieldassist.IControlContentAdapter#setControlContents(org.eclipse
+        * .swt.widgets.Control, java.lang.String, int)
+        */
+       public void setControlContents(Control control, String contents, int cursorPosition) {
+               ((StyledText)control).setText(contents);
+               ((StyledText)control).setCaretOffset(cursorPosition);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.jface.fieldassist.IControlContentAdapter#setCursorPosition(org.eclipse
+        * .swt.widgets.Control, int)
+        */
+       public void setCursorPosition(Control control, int index) {
+               ((StyledText)control).setCaretOffset(index);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.jface.fieldassist.IControlContentAdapter2#getSelection(org.eclipse.swt
+        * .widgets.Control)
+        */
+       public Point getSelection(Control control) {
+               return ((StyledText)control).getSelection();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see
+        * org.eclipse.jface.fieldassist.IControlContentAdapter2#setSelection(org.eclipse.swt
+        * .widgets.Control, org.eclipse.swt.graphics.Point)
+        */
+       public void setSelection(Control control, Point range) {
+               ((StyledText)control).setSelection(range);
+       }
+
+}