package org.vietspider.ui.htmlexplorer;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.sf.feeling.swt.win32.extension.widgets.CMenu;
import org.sf.feeling.swt.win32.extension.widgets.CMenuItem;
import org.sf.feeling.swt.win32.extension.widgets.PopupMenu;
import org.vietspider.html.HTMLNode;
import org.vietspider.html.path2.HTMLExtractor;
import org.vietspider.html.path2.NodePath;
import org.vietspider.html.path2.NodePathParser;
import org.vietspider.token.attribute.Attribute;
import org.vietspider.token.attribute.Attributes;
import org.vietspider.ui.XPWidgetTheme;
import org.vietspider.ui.widget.UIDATA;
public final class NodeEditor2 extends Composite {
public Text text;
private NodeSuggestion popup;
protected boolean hasFocus;
protected Listener listener, filter;
private HtmlExplorerActionListener explorer;
private AddPathButton dialog;
public NodeEditor2 (Composite parent, HtmlExplorerActionListener htmlExplorer) {
super (parent, SWT.BORDER);
this.setLayout(new FillLayout());
this.explorer = htmlExplorer;
text = new Text(this, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
text.setDoubleClickEnabled(false);
text.setFont(UIDATA.FONT_10B);
text.addKeyListener(new KeyListener() {
public void keyReleased(KeyEvent event) {
if (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN) {
event.doit = false;
if ((event.stateMask & SWT.ALT) != 0) {
// if (isDropped()) popup.setFocus ();
return;
}
if (isDropped()) {
popup.handleArrowKey(event);
return;
}
} else if(event.keyCode == SWT.ESC) {
if (isDropped()) {
dropped();
return;
}
} else if (event.keyCode == SWT.BS || event.keyCode == SWT.DEL) {
int pos = text.getCaretPosition();
String value = text.getText();
int index = pos - 1;
if(index < 0) {
if(popup != null) popup.dispose();
return;
}
char c = value.charAt(index);
if(c == '[' && (pos < value.length() && value.charAt(pos) == ']')) {
if(popup != null) popup.dispose();
String [] templates = new String[]{"*", "i>", "i<", "i%2=", "i%3=", "i%4=", "i/2=", "i/3="};
if(popup != null) popup.dispose();
popup = new NodeSuggestion(NodeEditor2.this, templates, NodeSuggestion.EXPRESSION);
return;
}
}
}
@Override
public void keyPressed(KeyEvent event) {
dialog.computeShowArea(text);
if(event.keyCode == SWT.CR) {
event.doit = false;
if (isDropped()) {
String pattern = null;
if(popup.getList().getSelectionCount() > 0) {
pattern = popup.getList().getSelection()[0];
}
dropped();
if(pattern != null) {
insertText(pattern);
} else {
explorer.addEditItem();
}
return;
}
explorer.addEditItem();
}
int pos = text.getCaretPosition();
String value = text.getText();
if(event.character == '['&& isValidAttributeSuggestion(value,pos)) {
String path = text.getText(0, pos);
String [] templates = getAttributes(createNode(path));
if(templates.length > 0) {
if(popup != null) popup.dispose();
popup = new NodeSuggestion(NodeEditor2.this, templates, NodeSuggestion.ATTRIBUTE);
event.doit = false;
}
return;
} if(event.character == '.' && pos >= value.length()-1) {
String path = text.getText(0, pos-1);
String [] templates = getChildrenNames(createNode(path));
if(templates.length > 0) {
if(popup != null) popup.dispose();
popup = new NodeSuggestion(NodeEditor2.this, templates, NodeSuggestion.NODE);
}
return;
}
}
});
text.setDoubleClickEnabled(false);
text.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
if(e.button == 2) {
if(getText().trim().isEmpty()) return;
explorer.addEditItem();
}
}
@SuppressWarnings("unused")
public void mouseDoubleClick(MouseEvent e) {
handleDoubleClick();
// new TemplateHandlerAction(new char[]{'[', ']'}).handle(txtPath.text);
}
});
if(XPWidgetTheme.isPlatform()) {
PopupMenu popupMenu = new PopupMenu(text, XPWidgetTheme.THEME);
CMenu menu = new CMenu();
popupMenu.setMenu(menu);
text.setMenu(new Menu(text.getShell(), SWT.POP_UP));
CMenuItem item = new CMenuItem(SWT.NONE);
item.addSelectionListener(new SelectionAdapter() {
@SuppressWarnings("unused")
public void widgetSelected(SelectionEvent e) {
text.setText("");
}
});
item.setText("Clear");
menu.addItem(item);
} else {
Menu menu = new Menu(text.getShell(), SWT.POP_UP);
text.setMenu(menu);
MenuItem item = new MenuItem(menu, SWT.NONE);
item.addSelectionListener(new SelectionAdapter() {
@SuppressWarnings("unused")
public void widgetSelected(SelectionEvent e) {
text.setText("");
}
});
item.setText("Clear");
}
dialog = new AddPathButton(explorer, this);
}
void insertText(String pattern) {
int pos = text.getCaretPosition();
String value = text.getText();
value = value.substring(0, pos) + pattern + value.substring(pos);
text.setText(value);
text.setSelection(pos+pattern.length(), pos + pattern.length());
}
private boolean isDropped() {
return popup != null && !popup.isDisposed();
}
private void dropped() {
popup.dispose();
popup = null;
}
public String getText() { return text.getText(); }
public void setText(String value) {
text.setText(value);
if(popup != null) popup.dispose();
}
public Text getTextComponent() { return text; }
/*private void handle() {
int pos = text.getCaretPosition();
String value = text.getText();
int index = pos - 1;
if(index < 0) {
if(popup != null) popup.dispose();
return;
}
char c = value.charAt(index);
if(c == '.' && pos >= value.length()-1) {
String path = text.getText(0, pos-1);
String [] templates = getChildrenNames(createNode(path));
if(templates.length > 0) {
popup = new NodeSuggestion(this, templates, NodeSuggestion.NODE);
}
return;
} else if(c == '[' && (pos < value.length() && value.charAt(pos) == ']')) {
if(popup != null) popup.dispose();
String [] templates = new String[]{"*", "i>", "i<", "i%2=", "i%3=", "i%4=", "i/2=", "i/3="};
popup = new NodeSuggestion(this, templates, NodeSuggestion.EXPRESSION);
return;
} if(c == ']' && isValidAttributeSuggestion(value,pos)) {
String path = text.getText(0, pos);
String [] templates = getAttributes(createNode(path));
if(templates.length > 0) {
popup = new NodeSuggestion(this, templates, NodeSuggestion.ATTRIBUTE);
}
return;
}
index--;
if(popup != null) popup.dispose();
}*/
private HTMLNode createNode(String path) {
HTMLExtractor extractor = new HTMLExtractor();
NodePathParser pathParser = new NodePathParser();
if(path.endsWith("[.")) {
path = path.substring(0, path.length() - 2);
} else if(path.endsWith("[")) {
path = path.substring(0, path.length() - 1);
}
try {
NodePath nodePath = pathParser.toPath(path);
return extractor.lookNode(explorer.getDocument().getRoot(), nodePath);
} catch (Exception e) {
}
return null;
}
private String[] getChildrenNames(HTMLNode node) {
if(node == null) return new String[0];
List<HTMLNode> children = node.getChildren();
if(children == null
|| children.size() < 1) return new String[0];
String [] values = new String[children.size()];
for(int i = 0; i < children.size(); i++) {
HTMLNode child = children.get(i);
StringBuilder builder = new StringBuilder();
builder.append(child.getName().toString());
builder.append('[').append(getIndex(children, child)).append(']');
values[i] = builder.toString();
}
return values;
}
private int getIndex(List<HTMLNode> children, HTMLNode element){
int count = 0;
for(int i = 0; i < children.size(); i++){
if(children.get(i).isNode(element.getName())){
if(children.get(i) == element) return count;
count++;
}
}
return count;
}
private String[] getAttributes(HTMLNode node) {
if(node == null) return new String[0];
try {
Attributes attributes = node.getAttributes();
String [] values = new String[attributes.size()];
for(int i = 0; i < attributes.size(); i++) {
Attribute attr = attributes.get(i);
values[i] = "[" + attr.getName()+"=" + attr.getValue() + "]";
}
return values;
} catch(Exception exp) {
}
return new String[0];
}
private boolean isValidAttributeSuggestion(String value, int index) {
if(index >= value.length()) {
index = value.length() - 1;
} else {
index--;
}
int counter = 0;
while(index > -1) {
char c = value.charAt(index);
if(c == '.') break;
if(c == '[') counter++;
index--;
}
return counter == 1;
}
private void handleDoubleClick() {
int pos = text.getCaretPosition();
String value = text.getText();
if(pos < 0 || pos >= value.length()) {
if(popup != null) popup.dispose();
return;
}
int start = -1;
int index = pos;
while(index > -1) {
char c = value.charAt(index);
if(c == '[') {
start = index;
break;
} else if(c == '.') {
break;
}
index--;
}
if(start < 0) return;
int end = -1;
index = pos;
while(index < value.length()) {
char c = value.charAt(index);
if(c == ']') {
end = index;
break;
} else if(c == '.') {
break;
}
index++;
}
if(end < 0) return;
value = value.substring(0, start+1) + "*" + value.substring(end);
text.setText(value);
text.setSelection(end, end);
}
}