Leading and trailing white spaces are now rendered visibly

in the data browser.
This commit is contained in:
Ralf Wisser
2023-03-10 10:20:31 +01:00
parent 437d77ee85
commit 0d8e6e405c
7 changed files with 93 additions and 25 deletions
@@ -662,7 +662,9 @@ public class StringSearchPanel extends javax.swing.JPanel {
fgColor = Color.WHITE;
hlColor = "#ff9999";
}
String item = value.toString().trim();
String item = value.toString();
item = UIUtil.indicateLeadingAndTrailingSpaces(item);
String search = extendedSearchText(searchTextField.getText(), item).toUpperCase(Locale.ENGLISH);
int i = searchTextField.getText().endsWith(" ")? item.toUpperCase(Locale.ENGLISH).lastIndexOf(search) : item.toUpperCase(Locale.ENGLISH).indexOf(search);
if (i >= 0) {
@@ -815,6 +817,10 @@ public class StringSearchPanel extends javax.swing.JPanel {
return plainIsValid? searchTextField.getText() : combobox.getSelectedItem() instanceof String? (String) combobox.getSelectedItem() : searchTextField.getText();
}
public boolean isPlainValueFromCombobox() {
return plainIsValid? false : combobox.getSelectedItem() instanceof String? true : false;
}
private void createSchemaSelectionList(JPanel container, final List<MDSchema> vis) {
container.setLayout(new GridLayout(metaDataSource.getSchemas().size() + 1, 1));
Set<MDSchema> selectedSchemas = new HashSet<MDSchema>();
+25
View File
@@ -2278,6 +2278,31 @@ public class UIUtil {
"</html>";
}
private static Pattern leadingTrailingWSPattern = Pattern.compile("^(\\s*)(.*?)(\\s*)$");
public static char spaceIndicator = '\u23B5';
public static char tabIndicator = '\u21E5';
public static String indicateLeadingAndTrailingSpaces(String item) {
item = item.replace('\t', tabIndicator);
Matcher m = leadingTrailingWSPattern.matcher(item);
if (m.matches()) {
String leading = m.group(1);
String trainling = m.group(3);
if (leading.length() > 0 || trainling.length() > 0) {
StringBuilder sb = new StringBuilder();
for (int i = leading.length(); i > 0; --i) {
sb.append(spaceIndicator);
}
sb.append(m.group(2));
for (int i = trainling.length(); i > 0; --i) {
sb.append(spaceIndicator);
}
item = sb.toString();
}
}
return item;
}
public static void setClipboardContent(Transferable text) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
try {
@@ -75,7 +75,7 @@ public class BrowserContentCellEditor {
}
@Override
boolean isEditable(int columnType, Object content, BrowserContentCellEditor browserContentCellEditor) {
boolean isEditable(int columnType, Object content, boolean relaxed, BrowserContentCellEditor browserContentCellEditor) {
return true;
}
@@ -96,8 +96,8 @@ public class BrowserContentCellEditor {
}
@Override
boolean isEditable(int columnType, Object content, BrowserContentCellEditor browserContentCellEditor) {
return content == null || ((content instanceof String || content instanceof CellContentConverter.NCharWrapper) && (browserContentCellEditor.isInDetailsView() || !(content.toString().indexOf('\n') >= 0 || content.toString().indexOf('\t') >= 0)));
boolean isEditable(int columnType, Object content, boolean relaxed, BrowserContentCellEditor browserContentCellEditor) {
return content == null || ((content instanceof String || content instanceof CellContentConverter.NCharWrapper) && (browserContentCellEditor.isInDetailsView() || !(content.toString().indexOf('\n') >= 0 || !relaxed && content.toString().indexOf('\t') >= 0)));
}
@Override
@@ -117,8 +117,8 @@ public class BrowserContentCellEditor {
}
@Override
boolean isEditable(int columnType, Object content, BrowserContentCellEditor browserContentCellEditor) {
return content == null || (content instanceof CellContentConverter.NCharWrapper && (browserContentCellEditor.isInDetailsView() || !(content.toString().indexOf('\n') >= 0 || content.toString().indexOf('\t') >= 0)));
boolean isEditable(int columnType, Object content, boolean relaxed, BrowserContentCellEditor browserContentCellEditor) {
return content == null || (content instanceof CellContentConverter.NCharWrapper && (browserContentCellEditor.isInDetailsView() || !(content.toString().indexOf('\n') >= 0 || !relaxed && content.toString().indexOf('\t') >= 0)));
}
@Override
@@ -151,7 +151,7 @@ public class BrowserContentCellEditor {
}
@Override
boolean isEditable(int columnType, Object content, BrowserContentCellEditor browserContentCellEditor) {
boolean isEditable(int columnType, Object content, boolean relaxed, BrowserContentCellEditor browserContentCellEditor) {
return true;
}
@@ -242,7 +242,7 @@ public class BrowserContentCellEditor {
}
@Override
boolean isEditable(int columnType, Object content, BrowserContentCellEditor browserContentCellEditor) {
boolean isEditable(int columnType, Object content, boolean relaxed, BrowserContentCellEditor browserContentCellEditor) {
return true;
}
@@ -304,7 +304,7 @@ public class BrowserContentCellEditor {
}
@Override
boolean isEditable(int columnType, Object content, BrowserContentCellEditor browserContentCellEditor) {
boolean isEditable(int columnType, Object content, boolean relaxed, BrowserContentCellEditor browserContentCellEditor) {
return true;
}
@@ -314,7 +314,7 @@ public class BrowserContentCellEditor {
}
};
abstract boolean isEditable(int columnType, Object content, BrowserContentCellEditor browserContentCellEditor);
abstract boolean isEditable(int columnType, Object content, boolean relaxed, BrowserContentCellEditor browserContentCellEditor);
abstract String cellContentToText(int columnType, Object content);
abstract Object textToContent(int columnType, String text, Object oldContent);
abstract boolean useCaseIntensitiveOrderingInGUI();
@@ -394,7 +394,7 @@ public class BrowserContentCellEditor {
}
}
}
/**
* Is given cell editable?
*
@@ -403,6 +403,18 @@ public class BrowserContentCellEditor {
* @param content cell content
*/
public boolean isEditable(Table table, int column, Object content) {
return isEditable(table, column, content, false);
}
/**
* Is given cell editable?
*
* @param table the table
* @param column column number
* @param content cell content
* @param relaxed if <code>true</code>, content is editable iff it is uniquely convertable into SQL literal. No Need to edit it in a JTextField.
*/
public boolean isEditable(Table table, int column, Object content, boolean relaxed) {
if (column < 0 || column >= columnTypes.length) {
return false;
}
@@ -418,7 +430,7 @@ public class BrowserContentCellEditor {
if (content instanceof PObjectWrapper) {
content = ((PObjectWrapper) content).getValue();
}
return converter.isEditable(columnTypes[column], content, this);
return converter.isEditable(columnTypes[column], content, relaxed, this);
}
return false;
}
@@ -26,6 +26,7 @@ import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
@@ -5126,13 +5127,13 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
suffix = "";
}
} else {
valueAsString = String.valueOf(value);
valueAsString = UIUtil.indicateLeadingAndTrailingSpaces(String.valueOf(value));
suffix = "";
}
valueAsString = " " + valueAsString + suffix;
valueAsString = " " + (valueAsString.replace('\n', (char) 182)) + suffix;
}
}
return valueAsString.replace('\n', (char) 182);
return valueAsString;
}
}
@@ -5421,7 +5422,13 @@ public abstract class BrowserContentPane extends javax.swing.JPanel {
}
//set the editor as default on every column
inplaceEditorTextField.setBorder(new LineBorder(Color.black));
inplaceEditorTextField.setBorder(new LineBorder(Color.black) {
int spWidth = inplaceEditorTextField.getFontMetrics(inplaceEditorTextField.getFont()).stringWidth(" ");
public Insets getBorderInsets(Component c, Insets insets) {
Insets myInsets = super.getBorderInsets(c, insets);
return new Insets(myInsets.top, myInsets.left + spWidth + (PLAF.FLAT == UIUtil.plaf? 2 : 0), myInsets.bottom, myInsets.right);
}
});
DefaultCellEditor anEditor = new DefaultCellEditor(inplaceEditorTextField) {
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
@@ -561,7 +561,7 @@ public abstract class DetailsView extends javax.swing.JPanel {
if (finalV instanceof UIUtil.IconWithText) {
f.setText(((UIUtil.IconWithText) finalV).text);
} else {
f.setText(finalV == null ? "null" : finalV.toString());
f.setText(finalV== null? "null" : isEditable? finalV.toString() : UIUtil.indicateLeadingAndTrailingSpaces(finalV.toString()));
}
}
origText = null;
@@ -598,7 +598,7 @@ public abstract class DetailsView extends javax.swing.JPanel {
f.setText(((UIUtil.IconWithText) v).text);
textRows.add(new Object[] { textTable, textColumn, ((UIUtil.IconWithText) v).text });
} else {
f.setText(v == null? "null" : v.toString());
f.setText(v == null? "null" : isEditable? v.toString() : UIUtil.indicateLeadingAndTrailingSpaces(v.toString()));
textRows.add(new Object[] { textTable, textColumn, v == null? "" : v.toString() });
}
// f.setEnabled(v != null);
@@ -530,7 +530,10 @@ public class TabContentPanel extends javax.swing.JPanel {
if (sep != null || (v == UIUtil.NULL || v == null)) {
value = v;
} else {
value = rtrimRegExpr.matcher(value.toString().replace((char) 182, '\n')).replaceAll("");
value = value.toString().replace((char) 182, '\n');
value = value.toString().replace(UIUtil.spaceIndicator, ' ');
value = value.toString().replace(UIUtil.tabIndicator, '\t');
value = rtrimRegExpr.matcher(value.toString()).replaceAll("");
}
}
String cellContent = value == UIUtil.NULL || value == null? "" : value.toString();
@@ -1711,7 +1711,7 @@ public abstract class WhereConditionEditorPanel extends javax.swing.JPanel {
public void run() {
setValueFieldText(valueTextField, theSearchPanel.get(0).getPlainValue());
if (theSearchPanel.get(0).isExplictlyClosed()) {
accept(comparison, theSearchPanel.get(0).getPlainValue(), comparison.operator);
accept(comparison, theSearchPanel.get(0).getPlainValue(), theSearchPanel.get(0).isPlainValueFromCombobox(), comparison.operator);
if (initialColumn >= 0 && popupOnTop) {
if (REDUCED_OPACITY_FADE_START == 0) {
setVisible(false);
@@ -1862,7 +1862,7 @@ public abstract class WhereConditionEditorPanel extends javax.swing.JPanel {
public void run() {
boolean[] fromCache = new boolean[1];
boolean[] fromCacheFull = new boolean[1];
int[] incomplete = new int[1];
int[] incomplete = new int[2];
boolean[] withNull = new boolean[1];
incomplete[0] = 0;
LinkedHashMap<String, Integer> distinctExisting = null;
@@ -2011,7 +2011,11 @@ public abstract class WhereConditionEditorPanel extends javax.swing.JPanel {
protected void setStatus(int[] incomplete, LinkedHashMap<String, Integer> finalDistinctExisting) {
if (incomplete[0] > 0 || finalDistinctExisting.size() > MAX_NUM_DISTINCTEXISTINGVALUES) {
searchPanel.setStatus("incomplete"
+ (incomplete[0] > 0? (" (" + incomplete[0] + " missing)") : ("(>" + MAX_NUM_DISTINCTEXISTINGVALUES + " values)")),
+ (finalDistinctExisting.size() > MAX_NUM_DISTINCTEXISTINGVALUES? ("(>" + MAX_NUM_DISTINCTEXISTINGVALUES + " values)")
:
(" (" + (incomplete[0] % MAX_NUM_DISTINCTEXISTINGVALUES)
+ " missing"
+ (incomplete[0] > MAX_NUM_DISTINCTEXISTINGVALUES? ", multi-line text" : "") + ")")),
UIUtil.scaleIcon(searchPanel, warnIcon));
} else {
searchPanel.setStatus(null, null);
@@ -2226,7 +2230,7 @@ public abstract class WhereConditionEditorPanel extends javax.swing.JPanel {
} else {
result.put(IS_NOT_NULL, count - rc);
}
if (cellEditor.isEditable(table, columnIndex, obj)) {
if (cellEditor.isEditable(table, columnIndex, obj, true)) {
String text = cellEditor.cellContentToText(columnIndex, obj);
if (text.length() <= MAX_TEXT_LENGTH) {
count = result.get(text);
@@ -2239,6 +2243,11 @@ public abstract class WhereConditionEditorPanel extends javax.swing.JPanel {
incomplete[0]++;
}
} else {
if (incomplete[0] < MAX_NUM_DISTINCTEXISTINGVALUES) {
if (String.valueOf(obj).indexOf('\n') >= 0) {
incomplete[0] += MAX_NUM_DISTINCTEXISTINGVALUES;
}
}
incomplete[0]++;
}
}
@@ -2281,10 +2290,16 @@ public abstract class WhereConditionEditorPanel extends javax.swing.JPanel {
}
return 12;
}
private void accept(Comparison comparison, String value, Operator operator) {
accept(comparison, value, false, operator);
}
protected void accept(Comparison comparison, String value, Operator operator) {
private void accept(Comparison comparison, String value, boolean dontTrim, Operator operator) {
if (value != null) {
value = value.trim();
if (!dontTrim) {
value = value.trim();
}
if ("true".equals(value) || "false".equals(value)) {
session.setSessionProperty(getClass(), "TFDebugInfo", "(" + comparison.column + ", " + comparison.operator + ")");
}