Index: geniuswebcore/geniusweb/simplerunner/NegoRunner.py
===================================================================
--- geniuswebcore/geniusweb/simplerunner/NegoRunner.py	(revision 87)
+++ geniuswebcore/geniusweb/simplerunner/NegoRunner.py	(revision 88)
@@ -17,9 +17,12 @@
 from geniusweb.protocol.NegoState import NegoState
 from geniusweb.simplerunner.ClassPathConnectionFactory import ClassPathConnectionFactory
+from geniusweb.simplerunner.Runner import Runner
+from geniusweb.simplerunner.gui.GUI import GUI
 
 
 class StdOutReporter (Reporter):
+
 	def log(self, level:int , msg:str, exc:Optional[BaseException]=None):
-		if level >= logging.WARNING :
+		if level >= logging.WARNING:
 			print(logging.getLevelName(level) + ":" + msg, file=sys.stderr)
 		else:
@@ -29,6 +32,4 @@
 class NegoRunner:
 	'''
-	WARNING DO NOT USE. NOT WORKING YET. 
-	
 	A simple tool to run a negotiation stand-alone, without starting the servers.
 	All referred files and classes need to be stored locally (or be in the
@@ -47,95 +48,18 @@
 	'''
 
-	_properlyStopped:bool = False
-	_LOOPTIME = 200 # ms
-	_FINALWAITTIME = 5000 # ms
-
-	def __init__(self, settings:NegoSettings ,
-			connectionfactory:ClassPathConnectionFactory , logger:Reporter ,
-			maxruntime:int):
-		'''
-		@param settings          the {@link NegoSettings}
-		@param connectionfactory the {@link ProtocolToPartyConnFactory}
-		@param logger            the {@link Reporter} to log problems
-		@param maxruntime        limit in millisecs. Ignored if 0
-		'''
-		if settings == None  or connectionfactory == None:
-			raise ValueError("Arguments must be not null");
-		self._settings = settings;
-		self._log = logger;
-		self._protocol = settings.getProtocol(self._log);
-		self._connectionfactory = connectionfactory;
-		self._maxruntime = maxruntime;
-		self._jackson=ObjectMapper()
-
-	def isProperlyStopped(self)->bool:
-		'''
-		@return true if the runner has finished
-		'''
-		return self._properlyStopped
-
-	def run(self):
-		this=self
-		class protocolListener(Listener[ProtocolEvent]):
-			def notifyChange(self, evt: ProtocolEvent):
-				this._handle(evt)
-
-		self._protocol.addListener(protocolListener())
-		self._protocol.start(self._connectionfactory)
-		remainingtime = self._maxruntime;
-		while not self._properlyStopped and  (self._maxruntime == 0 or remainingtime > 0):
-			time.sleep(self._LOOPTIME/1000.)
-			remainingtime -= self._LOOPTIME
-		self._log.log(logging.INFO, "Waiting for connection closure")
-
-		remainingtime = self._FINALWAITTIME;
-		while remainingtime > 0 and\
-			len(self._connectionfactory.getOpenConnections())!=0:
-				time.sleep(self._LOOPTIME/1000.)
-				remainingtime -= self._LOOPTIME
-			
-		openconn  = self._connectionfactory.getOpenConnections()
-		if len(openconn)!=0:
-			self._log.log(logging.WARNING, "Connections " + str(openconn)\
-					+ " did not close properly at end of run")
-		self._log.log(logging.INFO, "end run")
-
-	def _handle(self, evt:ProtocolEvent ):
-		if isinstance(evt , CurrentNegoState) and \
-			evt.getState().isFinal(1000*time.time()):
-				self._stop()
-
-	def _stop(self):
-		self._logFinal(logging.INFO, self._protocol.getState())
-		self._properlyStopped =True
-
-	def _logFinal(self, level:int , state: NegoState):
-		'''
-		Separate so that we can intercept this when mocking, as this will crash
-		on mocks because {@link #jackson} can not handle mocks.
-		
-		@param level the log {@link Level}, eg logging.WARNING
-		@param state the {@link NegoState} to log
-		'''
-		try:
-			self._log.log(level, "protocol ended normally: "
-					+ json.dumps(self._jackson.toJson(self._protocol.getState())))
-		except Exception as e: # catch json issues
-			traceback.print_exc()
-
-	def getProtocol(self) ->NegoProtocol :
-		'''
-		@return protocol that runs/ran the session.
-		'''
-		return self._protocol
-
 	@staticmethod
-	def main( args:List[str]) :
+	def main(args:List[str]):
 		'''
 		The main runner
 		
-		@param args should have 1 argument, the settings.json file to be used.
+		@param args should have 0 or 1 argument. If 0 arguments, the {@link GUI}
+		            is started. If one argoment, it should be a filename
+		            containing a settings.json file. That session is then run.
 		@throws IOException if problem occurs
 		'''
+		if len(args) == 0:
+			GUI.main([])
+			return 
+		
 		if len(args) != 1:
 			NegoRunner.showusage()
@@ -143,8 +67,8 @@
 		
 		serialized = Path(args[0]).read_text("utf-8")
-		settings:NegoSettings  = ObjectMapper().parse(json.loads(serialized),
-						NegoSettings) #type:ignore
+		settings:NegoSettings = ObjectMapper().parse(json.loads(serialized),
+						NegoSettings)  # type:ignore
 
-		runner = NegoRunner(settings,
+		runner = Runner(settings,
 				ClassPathConnectionFactory(), StdOutReporter(), 0)
 		runner.run()
@@ -156,8 +80,7 @@
 		print("The settings.json file should contain the NegoSettings.")
 		print("See the settings.json example file and the GeniusWeb wiki pages. ")
-
 	
 
-if __name__ == '__main__':   
-	NegoRunner.main([sys.argv[1]])
+if __name__ == '__main__': 
+	NegoRunner.main(sys.argv[1:])
 	
