package eu.jucy.gui.texteditor; import helpers.GH; import java.util.List; import java.util.SortedMap; import java.util.concurrent.CopyOnWriteArrayList; import logger.LoggerFactory; import org.apache.log4j.Logger; import org.eclipse.jface.bindings.keys.KeyStroke; import org.eclipse.jface.fieldassist.ContentProposalAdapter; import org.eclipse.jface.fieldassist.IContentProposalListener2; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Text; import eu.jucy.eliza.ElizaSession; import eu.jucy.gui.ApplicationWorkbenchWindowAdvisor; import eu.jucy.gui.texteditor.hub.HubEditor; import eu.jucy.gui.texteditor.pmeditor.PMEditor; import uc.DCClient; import uc.IUser; import uc.IUser.PMResult; import uc.protocols.hub.Hub; import uc.protocols.hub.PrivateMessage; import uihelpers.SUIJob; public abstract class SendingWriteline { private static final Logger logger = LoggerFactory.make(); private static final int HISTORYTYPED = 20; public static boolean lastKeyWasEnter; public static long lastKeyPressed; /** * * @param timedifmillis how much difference should be at least between typing and opening a popup.. * @return true if last key pressed was enter ... or nothing was typed for provided time.. */ public static boolean checkOpenPopUpExecution(long timedifmillis) { return lastKeyWasEnter || lastTypingOccurred(timedifmillis); } public static boolean lastTypingOccurred(long timedifmillis) { return lastKeyPressed + timedifmillis < System.currentTimeMillis(); } protected final Text writeline; protected final DCClient dcc; /** * sent messages stuff .. * store for messages sent recently.. * -> navigateing.. */ private final List<String> sentMessages = new CopyOnWriteArrayList<String>(); public List<String> getSentMessages() { return sentMessages; } // private ListIterator<String> ctrlUpPosition; // //if thats tool ong ago -> reset ctrlUpPosition // private long recentCTRLUpPressedTime = System.currentTimeMillis(); // private String savedText; //save text that was currently in the writeline before up and down were pressed.. /** * com-variable to determine if text can be sent to hub * by pressing enter.. only when no completion proposal is open * text should be sent.. */ private boolean proposalClosed = true; private final CommandInterpreter interpreter; private boolean ctrlPressed = false; /** * * @param line - the Text where the user types * @param users - the users needed for completion (kept in the HubEditor) */ public SendingWriteline(Text line,SortedMap<String,IUser> users, CommandInterpreter inter) { this.writeline = line; this.interpreter = inter; this.dcc = ApplicationWorkbenchWindowAdvisor.get(); UserNameCompleter unc = new UserNameCompleter(users); ContentProposalAdapter cpa = new ContentProposalAdapter( writeline,unc,unc, KeyStroke.getInstance(KeyStroke.NO_KEY,SWT.TAB ),null); cpa.setPopupSize(new Point(300,200)); //disables sending while proposal pop-up is open IContentProposalListener2 cpl= new IContentProposalListener2() { public void proposalPopupClosed(ContentProposalAdapter adapter) { new SUIJob() { //done in UIjob so it is postponed until the key listener is called (Enter Key that was used for closing the proposal) @Override public void run() { proposalClosed = true; } }.schedule(); logger.debug("proposal popup closed"); } public void proposalPopupOpened(ContentProposalAdapter adapter) { proposalClosed = false; logger.debug("proposal popup opened"); } }; cpa.addContentProposalListener(cpl); WrittenTextContentProposal wtcp = new WrittenTextContentProposal(this); ContentProposalAdapter cpb = new ContentProposalAdapter( writeline,wtcp,wtcp, KeyStroke.getInstance(SWT.CTRL,SWT.ARROW_UP ),null); cpb.setPopupSize(new Point(500,200)); cpb.addContentProposalListener(cpl); writeline.addKeyListener(new KeyAdapter() { public void keyPressed(final KeyEvent e) { lastKeyWasEnter = false; lastKeyPressed = System.currentTimeMillis(); if (e.keyCode == SWT.CTRL) { ctrlPressed = true; } //logger.info("ctrl up or down pressed "+e.keyCode+ " "+SWT.ARROW_UP); // if (proposalClosed && ctrlPressed && (e.keyCode == SWT.ARROW_UP|| e.keyCode == SWT.ARROW_DOWN)) { // ctrlAndUpOrDownPressed(e.keyCode == SWT.ARROW_UP ); // //logger.info("ctrl up or down pressed"); // e.doit = false; // return; // } if (proposalClosed && !ctrlPressed && (e.keyCode == SWT.KEYPAD_CR || e.keyCode == SWT.CR)) { lastKeyWasEnter = true; e.doit = false; //else the 'CR' would just be in the way and represent a newline String sendText = writeline.getText(); if (!GH.isEmpty(sendText.trim())) { if (interpreter.isCommand(sendText)) { interpreter.executeCommand(sendText); writeline.setText(""); logger.debug("line is command. "+sendText); } else { send(sendText); sentMessages.add(0,sendText); if (sentMessages.size() > HISTORYTYPED) { sentMessages.remove(sentMessages.size()-1); } logger.debug("line is chat message "+sendText); writeline.setText(""); } } } } @Override public void keyReleased(KeyEvent e) { if (SWT.CTRL == e.keyCode) { ctrlPressed = false; } } }); writeline.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { ctrlPressed = false; } }); } // /** // * moves to the next sentMessage .. // * if nothing is pressed for more than 10 secs we forget where we were.. // * @param up - if true move up else down.. // */ // private void ctrlAndUpOrDownPressed(boolean up) { // if (ctrlUpPosition == null || System.currentTimeMillis()-recentCTRLUpPressedTime > 10000) { // ctrlUpPosition = sentMessages.listIterator(); // savedText = writeline.getText(); // } // // if (up?ctrlUpPosition.hasNext(): ctrlUpPosition.hasPrevious()) { // writeline.setText(up ? ctrlUpPosition.next(): ctrlUpPosition.previous()); // } else if (!up) { //if its down and has no previous -> set original text // writeline.setText(savedText); // } // // recentCTRLUpPressedTime = System.currentTimeMillis(); // } public abstract void send(String s); public Text getWriteline() { return writeline; } public static class HubSendingWriteline extends SendingWriteline { private final Hub hub; public HubSendingWriteline(Text line, SortedMap<String, IUser> users, Hub hub,HubEditor he) { super(line, users, new CommandInterpreter(hub,he)); this.hub = hub; } @Override public void send(final String s) { dcc.executeDir(new Runnable() { public void run() { hub.sendMM(s, false); } }); if (dcc.isAway()) { dcc.setAway(false); } } } public static class UserSendingWriteline extends SendingWriteline { private final IUser usr; private final PMEditor pme; private final ElizaSession elizaSession; public UserSendingWriteline(Text line, SortedMap<String, IUser> users, IUser other, PMEditor pme) { super(line, users, new CommandInterpreter(other,pme)); this.usr = other; this.pme = pme; elizaSession = other.getHub().getSelf().equals(other)?new ElizaSession():null; } @Override public void send(final String s) { if (elizaSession == null) { dcc.executeDir(new Runnable() { public void run() { PMResult pmres = usr.sendPM(s, false, true); if (pmres == PMResult.STORED) { pme.storedPM(usr,s, false); } } }); } else { pme.pmReceived(new PrivateMessage(usr, usr, s, false)); new SUIJob(writeline) { @Override public void run() { pme.appendText("<Psychotherapist> "+ elizaSession.saySomethingToEliza(s), null, MessageType.CHAT); } }.schedule(GH.nextInt(2000)+1000); } if (dcc.isAway()) { dcc.setAway(false); } } } }