diff --git a/Core/src/main/scala/org/workcraft/services/Format.scala b/Core/src/main/scala/org/workcraft/services/Format.scala index ffc480f6..26ff66a8 100644 --- a/Core/src/main/scala/org/workcraft/services/Format.scala +++ b/Core/src/main/scala/org/workcraft/services/Format.scala @@ -7,4 +7,5 @@ object Format { case object LolaPetriNet extends Format("Petri Net in LoLA format", ".lola") case object WorkcraftPetriNet extends Format("Petri Net in Workcraft format", ".pn") case object Dot extends Format("GraphViz dot", ".dot") -} \ No newline at end of file + case object Llnet extends Format("Petri Net in PEP tool format", ".ll_net") +} diff --git a/Core/src/main/scala/org/workcraft/services/Module.scala b/Core/src/main/scala/org/workcraft/services/Module.scala index 33167801..6c921cf2 100644 --- a/Core/src/main/scala/org/workcraft/services/Module.scala +++ b/Core/src/main/scala/org/workcraft/services/Module.scala @@ -1,8 +1,6 @@ package org.workcraft.services -import org.workcraft.pluginmanager.Plugin - -trait Module extends Plugin { +trait Module { def name: String def description: String = name def serviceProvider: GlobalServiceProvider diff --git a/Core/src/main/scala/org/workcraft/services/ServiceManager.scala b/Core/src/main/scala/org/workcraft/services/ServiceManager.scala index f77a16ff..a026d7d5 100644 --- a/Core/src/main/scala/org/workcraft/services/ServiceManager.scala +++ b/Core/src/main/scala/org/workcraft/services/ServiceManager.scala @@ -1,8 +1,7 @@ package org.workcraft.services -import org.workcraft.pluginmanager.PluginManager class GlobalServiceManager (val modules: List[Module]) extends GlobalServiceProvider { val serviceProviders = modules.map(_.serviceProvider) def implementations[T] (service: Service[GlobalScope, T]) = serviceProviders.flatMap(_.implementations(service)).toList -} \ No newline at end of file +} diff --git a/FSMPlugin/src/main/scala/org/workcraft/plugins/fsm/Module.scala b/FSMPlugin/src/main/scala/org/workcraft/plugins/fsm/Module.scala index afa02301..55f73ce4 100644 --- a/FSMPlugin/src/main/scala/org/workcraft/plugins/fsm/Module.scala +++ b/FSMPlugin/src/main/scala/org/workcraft/plugins/fsm/Module.scala @@ -34,7 +34,7 @@ object FSMServiceProvider extends GlobalServiceProvider { } } -class PetrifyModule extends Module { +class FSMModule extends Module { def name = "Finite State Machine" def serviceProvider = FSMServiceProvider } diff --git a/Gui/src/main/scala/org/workcraft/gui/CreateWorkDialog.scala b/Gui/src/main/scala/org/workcraft/gui/CreateWorkDialog.scala index 843154e0..6a1ef4eb 100644 --- a/Gui/src/main/scala/org/workcraft/gui/CreateWorkDialog.scala +++ b/Gui/src/main/scala/org/workcraft/gui/CreateWorkDialog.scala @@ -32,7 +32,7 @@ import java.awt.Font import org.workcraft.scala.effects.IO import org.workcraft.scala.effects.IO._ -class CreateWorkDialog private (models: List[NewModelImpl]) extends JDialog { +class CreateWorkDialog private (models: List[NewModelImpl], owner: Window) extends JDialog(owner) { class ListElement(val newModel: NewModelImpl) { override def toString = newModel.name } @@ -157,10 +157,10 @@ object CreateWorkDialog { JOptionPane.showMessageDialog(parentWindow, "Workcraft was unable to find any plug-ins that could create a new model.\n\nReconfiguring Workcraft (Utility->Reconfigure) might fix this.\n\nIf you are running Workcraft from a development environment such as Eclipse,\nplease make sure to add the plug-in classes to the classpath in run configuration. ", "Warning", JOptionPane.WARNING_MESSAGE) None } else { - val dialog = new CreateWorkDialog(models) + val dialog = new CreateWorkDialog(models, parentWindow) GUI.centerAndSizeToParent(dialog, parentWindow) dialog.setVisible(true) dialog.choice.map((_,dialog.chkOpen.isSelected())) } } -} \ No newline at end of file +} diff --git a/Gui/src/main/scala/org/workcraft/gui/FileMenu.scala b/Gui/src/main/scala/org/workcraft/gui/FileMenu.scala index 5d0aa834..55e517aa 100644 --- a/Gui/src/main/scala/org/workcraft/gui/FileMenu.scala +++ b/Gui/src/main/scala/org/workcraft/gui/FileMenu.scala @@ -30,7 +30,7 @@ import scalaz.Scalaz._ import org.workcraft.services.ExportError import javax.swing.JOptionPane -class FileMenu(services: () => GlobalServiceManager, mainWindow: MainWindow, newModel: ((NewModelImpl, Boolean)) => IO[Unit]) extends ReactiveMenu("File") { +class FileMenu(services: GlobalServiceManager, mainWindow: MainWindow, newModel: ((NewModelImpl, Boolean)) => IO[Unit]) extends ReactiveMenu("File") { def handleExportError(error: Option[ExportError]): IO[Unit] = error match { case None => IO.Empty case Some(error) => ioPure.pure { JOptionPane.showMessageDialog(mainWindow, error match { case ExportError.Exception(e) => e.toString(); case ExportError.Message(m) => m }, "Error", JOptionPane.ERROR_MESSAGE) } @@ -39,17 +39,17 @@ class FileMenu(services: () => GlobalServiceManager, mainWindow: MainWindow, new // Must be lazy because Scala allows to read uninitialized values lazy val items = mainWindow.editorInFocus.map(editor => { val newWork = menuItem("New work", Some('N'), Some(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK)), - CreateWorkDialog.show(services().implementations(NewModelService), mainWindow) >>= { case Some(choice) => newModel(choice); case None => IO.Empty }) + CreateWorkDialog.show(services.implementations(NewModelService), mainWindow) >>= { case Some(choice) => newModel(choice); case None => IO.Empty }) - val open = menuItem("Open file...", Some('O'), Some(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK)), OpenDialog.open(mainWindow, services()) >>= { case Some(model) => mainWindow.openEditor(model); case None => IO.Empty }) + val open = menuItem("Open file...", Some('O'), Some(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK)), OpenDialog.open(mainWindow, services) >>= { case Some(model) => mainWindow.openEditor(model); case None => IO.Empty }) val save = editor match { case Some(e) => { - val save = menuItem("Save", Some('S'), Some(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK)), SaveDialog.saveAs(mainWindow, e.content.model, services()) >>= { + val save = menuItem("Save", Some('S'), Some(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK)), SaveDialog.saveAs(mainWindow, e.content.model, services) >>= { case Some(job) => job >>= handleExportError case None => IO.Empty }) - val saveAs = menuItem("Save as...", Some('a'), None, SaveDialog.saveAs(mainWindow, e.content.model, services()) >>= { case Some(job) => job >>= handleExportError; case None => IO.Empty }) + val saveAs = menuItem("Save as...", Some('a'), None, SaveDialog.saveAs(mainWindow, e.content.model, services) >>= { case Some(job) => job >>= handleExportError; case None => IO.Empty }) List(save, saveAs) } case None => { @@ -85,7 +85,7 @@ class FileMenu(services: () => GlobalServiceManager, mainWindow: MainWindow, new case Some(e) => { val defaultFormat = e.content.model.implementation(DefaultFormatService) - val exporters = services().implementations(ExporterService).map(exp => (exp.targetFormat, exp.export(e.content.model))) + val exporters = services.implementations(ExporterService).map(exp => (exp.targetFormat, exp.export(e.content.model))) .flatMap({ case (format, Right(job)) if (defaultFormat.map(_ != format).getOrElse(true)) => Some((format, job)); case _ => None }) exportMenu(e.content.model, exporters) @@ -99,4 +99,4 @@ class FileMenu(services: () => GlobalServiceManager, mainWindow: MainWindow, new }) setMnemonic('F') -} \ No newline at end of file +} diff --git a/Gui/src/main/scala/org/workcraft/gui/GUI.scala b/Gui/src/main/scala/org/workcraft/gui/GUI.scala index f329a264..a3d0c4f3 100644 --- a/Gui/src/main/scala/org/workcraft/gui/GUI.scala +++ b/Gui/src/main/scala/org/workcraft/gui/GUI.scala @@ -29,7 +29,7 @@ import java.awt.Insets import java.awt.Dimension object GUI { - def loadImageFromResource(path: String): Either[Throwable, BufferedImage] = ClassLoader.getSystemResource(path) match { + def loadImageFromResource(path: String): Either[Throwable, BufferedImage] = this.getClass().getClassLoader().getResource(path) match { case null => Left(new IOException("Resource not found: " + path)) case url => try { Right(ImageIO.read(url)) } catch { case e => Left(e) } } @@ -57,7 +57,7 @@ object GUI { } def createIconFromImage(resourcePath: String): IO[Option[ImageIcon]] = ioPure.pure { - val res = ClassLoader.getSystemResource(resourcePath) + val res = this.getClass().getClassLoader().getResource(resourcePath) if (res == null) None else @@ -73,7 +73,7 @@ object GUI { val parser = XMLResourceDescriptor.getXMLParserClassName() val f = new SAXSVGDocumentFactory(parser) - val document = f.createDocument(ClassLoader.getSystemResource(path).toString()) + val document = f.createDocument(this.getClass().getClassLoader().getResource(path).toString()) val userAgentAdapter = new UserAgentAdapter() val bridgeContext = new BridgeContext(userAgentAdapter) @@ -154,4 +154,4 @@ object GUI { val lm = g.getFont().getLineMetrics(message, g.getFontRenderContext()) g.drawString(message, r.x, r.y + r.height - lm.getDescent().toInt) }) -} \ No newline at end of file +} diff --git a/Gui/src/main/scala/org/workcraft/gui/Main.scala b/Gui/src/main/scala/org/workcraft/gui/Main.scala index e984d822..529b71b0 100644 --- a/Gui/src/main/scala/org/workcraft/gui/Main.scala +++ b/Gui/src/main/scala/org/workcraft/gui/Main.scala @@ -1,6 +1,6 @@ package org.workcraft.gui +import java.awt.Window import org.workcraft.logging.StandardStreamLogger -import org.workcraft.pluginmanager.PluginManager import java.util.UUID import org.workcraft.services.GlobalServiceManager import org.workcraft.services.Module @@ -24,9 +24,7 @@ object Main { implicit val logger = () => currentLogger - val version = UUID.fromString("dd10f600-4769-11e1-b86c-0800200c9a66") val configDirPath = System.getProperty("user.home") + File.separator + ".workcraft" - val pluginPackages = List("org.workcraft.plugins") def configFilePath(fileName: String) = configDirPath + File.separator + fileName @@ -44,34 +42,12 @@ object Main { unsafeInfo("Configuration directory OK") } - private def shutdown(mainWindow: MainWindow)(implicit logger: () => Logger[IO]) = { - currentLogger = new StandardStreamLogger - unsafeInfo("Shutting down") - - GuiConfiguration.save(configFilePath("gui.conf"), mainWindow.guiConfiguration) - - mainWindow.setVisible(false) - - unsafeInfo("Have a nice day!") - System.exit(0) - } - - def loadPlugins(reconfigure: Boolean) = new PluginManager(version, pluginPackages, configFilePath("manifest"), reconfigure) - - def main(args: Array[String]) = { + def main(configDescription: String, globalServices: GlobalServiceManager, args: Array[String]) = { unsafeInfo("Welcome to Workcraft 2.2: Return of The Deadlock") - unsafeInfo("This build's version ID is " + version.toString()) + unsafeInfo("This build is using " + configDescription) checkConfig - var pluginManager = loadPlugins(false) - var globalServices = new GlobalServiceManager(pluginManager.plugins(classOf[Module]).map(_.singleton).toList) - - val reconfigure = ioPure.pure { - pluginManager = loadPlugins(true) - globalServices = new GlobalServiceManager(pluginManager.plugins(classOf[Module]).map(_.singleton).toList) - } - unsafeInfo("Starting GUI") val guiConfiguration = GuiConfiguration.load(configFilePath("gui.conf")) @@ -81,22 +57,29 @@ object Main { JDialog.setDefaultLookAndFeelDecorated(true) UIManager.put(SubstanceLookAndFeel.TABBED_PANE_CONTENT_BORDER_KIND, TabContentPaneBorderKind.SINGLE_FULL) - SwingUtilities.invokeLater(new Runnable { - def run = { - - val mainWindow = new MainWindow(() => globalServices, reconfigure, shutdown, guiConfiguration) + var mainWindow:MainWindow = null - mainWindow.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE) - mainWindow.addWindowListener(new WindowAdapter() { - override def windowClosing(e: WindowEvent) = shutdown(mainWindow) - }) + SwingUtilities.invokeAndWait(new Runnable { + def run = { + mainWindow = new MainWindow(globalServices, guiConfiguration) currentLogger = mainWindow.loggerWindow unsafeInfo("Now in GUI mode. Welcome to Workcraft 2.2: Return of The Deadlock!") mainWindow.setVisible(true) - } - }) + }}) + + mainWindow.synchronized { + mainWindow.wait() + } + + currentLogger = new StandardStreamLogger + + unsafeInfo("Shutting down") + + GuiConfiguration.save(configFilePath("gui.conf"), mainWindow.guiConfiguration) + + unsafeInfo("Have a nice day!") } -} \ No newline at end of file +} diff --git a/Gui/src/main/scala/org/workcraft/gui/MainMenu.scala b/Gui/src/main/scala/org/workcraft/gui/MainMenu.scala index 1b735ed1..d8d0dad1 100644 --- a/Gui/src/main/scala/org/workcraft/gui/MainMenu.scala +++ b/Gui/src/main/scala/org/workcraft/gui/MainMenu.scala @@ -11,21 +11,18 @@ import javax.swing.JComponent import org.workcraft.scala.effects.IO class MainMenu( - mainWindow: MainWindow, utilityWindows: List[DockableWindow[_ <: JComponent]], - services: () => GlobalServiceManager, - newModel: ((NewModelImpl, Boolean)) => IO[Unit], - reconfigure: IO[Unit]) extends JMenuBar { + mainWindow: MainWindow, + utilityWindows: List[DockableWindow[_ <: JComponent]], + services: GlobalServiceManager, + newModel: ((NewModelImpl, Boolean)) => IO[Unit] +) extends JMenuBar { val fileMenu = new FileMenu(services, mainWindow, newModel) val editMenu = new EditMenu(mainWindow) val windowsMenu = new UtilityWindowsMenu(utilityWindows) val toolsMenu = new ToolsMenu(services, mainWindow) - val utilityMenu = new JMenu("Utility") - utilityMenu.setMnemonic('U') - utilityMenu.add(GUI.menuItem("Reconfigure", Some('R'), None, reconfigure)) add(fileMenu) add(editMenu) add(windowsMenu) add(toolsMenu) - add(utilityMenu) -} \ No newline at end of file +} diff --git a/Gui/src/main/scala/org/workcraft/gui/MainWindow.scala b/Gui/src/main/scala/org/workcraft/gui/MainWindow.scala index 0d29b9fd..a9e0ebd4 100644 --- a/Gui/src/main/scala/org/workcraft/gui/MainWindow.scala +++ b/Gui/src/main/scala/org/workcraft/gui/MainWindow.scala @@ -44,13 +44,19 @@ import java.awt.event.FocusListener import java.awt.event.FocusEvent class MainWindow( - val globalServices: () => GlobalServiceManager, - reconfigure: IO[Unit], - shutdown: MainWindow => Unit, + val globalServices: GlobalServiceManager, configuration: Option[GuiConfiguration]) extends JFrame { val loggerWindow = new LoggerWindow implicit val implicitLogger: () => Logger[IO] = () => loggerWindow + + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE) + + addWindowListener(new WindowAdapter() { + override def windowClosing(e: WindowEvent) = exit.unsafePerformIO + }) + + applyIconManager applyGuiConfiguration(configuration) @@ -83,7 +89,7 @@ class MainWindow( var openEditors = List[DockableWindow[ModelEditorPanel]]() - val menu = new MainMenu(this, List(loggerDockable, toolboxDockable, propEdDockable), globalServices, { case (m, b) => newModel(m, b) }, reconfigure) + val menu = new MainMenu(this, List(loggerDockable, toolboxDockable, propEdDockable), globalServices, { case (m, b) => newModel(m, b) }) this.setJMenuBar(menu) def closeUtilityWindow(window: DockableWindow[_ <: JComponent]) = { @@ -187,5 +193,11 @@ class MainWindow( DockingManager.undock(editorDockable) } - def exit = ioPure.pure { shutdown(this) } -} \ No newline at end of file + def exit = ioPure.pure { + setVisible(false) + dispose() + this.synchronized { + notify() + } + } +} diff --git a/Gui/src/main/scala/org/workcraft/gui/ToolsMenu.scala b/Gui/src/main/scala/org/workcraft/gui/ToolsMenu.scala index fc48d431..e44b0cdb 100644 --- a/Gui/src/main/scala/org/workcraft/gui/ToolsMenu.scala +++ b/Gui/src/main/scala/org/workcraft/gui/ToolsMenu.scala @@ -8,10 +8,10 @@ import org.workcraft.scala.effects.IO import javax.swing.JMenu import org.workcraft.gui.GUI._ -class ToolsMenu(services: () => GlobalServiceManager, mainWindow: MainWindow) extends ReactiveMenu("Tools") { +class ToolsMenu(services: GlobalServiceManager, mainWindow: MainWindow) extends ReactiveMenu("Tools") { // Must be lazy because Scala allows to read uninitialized values lazy val items = { - val applicableTools = services().implementations(GuiToolService).map(tool => tool.run(mainWindow).map(_.map((tool, _)))).traverse(x => x).map(_.flatten) + val applicableTools = services.implementations(GuiToolService).map(tool => tool.run(mainWindow).map(_.map((tool, _)))).traverse(x => x).map(_.flatten) val makeMenu = (name: String, tools: List[(GuiTool, IO[Unit])]) => { val result = new JMenu(name) @@ -23,4 +23,4 @@ class ToolsMenu(services: () => GlobalServiceManager, mainWindow: MainWindow) ex } setMnemonic('T') -} \ No newline at end of file +} diff --git a/Gui/src/main/scala/org/workcraft/gui/modeleditor/ModelEditorPanel.scala b/Gui/src/main/scala/org/workcraft/gui/modeleditor/ModelEditorPanel.scala index 8960c8db..2ec3371b 100644 --- a/Gui/src/main/scala/org/workcraft/gui/modeleditor/ModelEditorPanel.scala +++ b/Gui/src/main/scala/org/workcraft/gui/modeleditor/ModelEditorPanel.scala @@ -1,4 +1,6 @@ package org.workcraft.gui.modeleditor +import java.awt.event.HierarchyEvent +import java.awt.event.HierarchyListener import javax.swing.JPanel import org.workcraft.dependencymanager.advanced.core.ExpressionBase import org.workcraft.dependencymanager.advanced.core.GlobalCache @@ -36,12 +38,12 @@ class ModelEditorPanel (val model: ModelServiceProvider, val editor: ModelEditor object Repainter { class Image - def start = { - val repainter = graphicalContent.map(_ => { ModelEditorPanel.this.repaint(); new Image }) - new Timer(30, new ActionListener { - override def actionPerformed(e: ActionEvent) = repainter.unsafeEval - }).start - } + + val repainter = graphicalContent.map(_ => { ModelEditorPanel.this.repaint(); new Image }) + + val timer = new Timer(30, new ActionListener { + override def actionPerformed(e: ActionEvent) = repainter.unsafeEval + }) } object Resizer extends ComponentAdapter { @@ -145,8 +147,21 @@ class ModelEditorPanel (val model: ModelServiceProvider, val editor: ModelEditor }) - Repainter.start - + addComponentListener(new ComponentAdapter { + override def componentShown (e:ComponentEvent) = { println ("shown!"); Repainter.timer.start; } + override def componentHidden (e:ComponentEvent) = { println ("hidden"); Repainter.timer.stop; } + }) + + addHierarchyListener ( new HierarchyListener { + override def hierarchyChanged (e: HierarchyEvent) = + if ((e.getChangeFlags & HierarchyEvent.SHOWING_CHANGED) != 0) { + if (isShowing) + Repainter.timer.start + else + Repainter.timer.stop + } + }) + override def paint(g: Graphics) = { val g2d = g.asInstanceOf[Graphics2D] // woohoo graphicalContent.unsafeEval.draw(g2d) diff --git a/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/LlnetFileOpen.scala b/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/LlnetFileOpen.scala new file mode 100644 index 00000000..ff08d693 --- /dev/null +++ b/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/LlnetFileOpen.scala @@ -0,0 +1,25 @@ +package org.workcraft.plugins.petri2 +import java.io.File +import org.workcraft.services.FileOpen +import org.workcraft.services.FileOpenJob +import org.workcraft.services.Format +import org.workcraft.scala.effects.IO._ +import scalaz.Scalaz._ + +object LlnetFileOpen extends FileOpen { + val description = "Workcraft .ll_net format importer" + val sourceFormat = Format.Llnet + + def checkFile(file: File) = ioPure.pure { file.getName().endsWith(".ll_net") } + + override def open(file: File) = checkFile(file).map( + if (_) + Some(FileOpenJob( + LlnetParser.parseLlnet(file) >>= { + case Left(error) => ioPure.pure { Left(error) } + case Right(llnet) => PetriNetBuilder.buildPetriNet(llnet) >>= + (pn => EditablePetriNet.create(pn).map( epn => Right( new PetriNetModel (epn)))) + })) + else + None) +} diff --git a/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/LlnetParser.scala b/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/LlnetParser.scala index 8ddc6c40..4df94fdb 100644 --- a/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/LlnetParser.scala +++ b/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/LlnetParser.scala @@ -11,6 +11,7 @@ import java.io.File import org.workcraft.scala.effects.IO._ import org.workcraft.scala.effects.IO import org.workcraft.dom.visual.connections.Polyline +import org.workcraft.dom.visual.connections.StaticVisualConnectionData import java.io.BufferedReader import java.io.FileReader import scalaz._ @@ -52,13 +53,13 @@ object LlnetParser extends Parsers with RegexParsers { } } - case class Llnet (format: Int, blocks: List[FinalBlockSpec], places: List[FinalPlaceSpec], - transitions: List[FinalTransitionSpec], producerArcs: List[ArcSpec], - consumerArcs: List[ArcSpec]) + case class Llnet (format: Int, blocks: List[FinalBlockSpec], places: List[FinalPlaceSpec], + transitions: List[FinalTransitionSpec], producerArcs: List[FinalArcSpec], + consumerArcs: List[FinalArcSpec]) case class FinalBlockSpec (num: Int, name: String, pos: (Int,Int), namePos: Option[(Int,Int)], meaning: Option[String], meaningPos: Option[(Int,Int)], - reference: Option[String], blocks: Option[String]) + reference: Option[String], blocks: Option[String]) case class FinalTransitionSpec (num: Int, name: String, pos: (Int,Int), namePos: Option[(Int,Int)], meaning: Option[String], meaningPos: Option[(Int,Int)], referece: Option[String], @@ -67,13 +68,15 @@ object LlnetParser extends Parsers with RegexParsers { case class FinalPlaceSpec (num: Int, name: String, pos: (Int,Int), namePos: Option[(Int,Int)], meaning: Option[String], meaningPos: Option[(Int,Int)], initialMarking: Int, currentMarking: Int, capacity: Option[Int] , reference: Option[String], - entry: Option[Boolean], exit: Option[Boolean], blocks: Option[String] ) + entry: Option[Boolean], exit: Option[Boolean], blocks: Option[String]) + case class FinalArcSpec ( from: Int, to: Int, weight: Int, weightPos: Option[(Int,Int)] = None, + visibility: Option[Int] = None, anchorPoint: Option[(Int,Int)] = None ) case class PlaceSpec (num: Option[Int] = None, name: Option[String] = None, pos: Option[(Int,Int)] = None, namePos: Option[(Int,Int)] = None, - meaning: Option[String] = None, meaningPos: Option[(Int,Int)] = None, initialMarking: Option[Int] = Some(0), - currentMarking: Option[Int] = Some(0), capacity: Option[Int] = None, reference: Option[String] = None, + meaning: Option[String] = None, meaningPos: Option[(Int,Int)] = None, initialMarking: Option[Int] = None, + currentMarking: Option[Int] = None, capacity: Option[Int] = None, reference: Option[String] = None, entry: Option[Boolean] = None, exit: Option[Boolean] = None, blocks: Option[String] = None) { @@ -84,7 +87,7 @@ object LlnetParser extends Parsers with RegexParsers { capacity + other.capacity, reference + other.reference, entry + other.entry, exit + other.exit, blocks + other.blocks) - def finalise = FinalPlaceSpec(num.get, name.get, pos.get, namePos, meaning, meaningPos, initialMarking.get, currentMarking.get, capacity, + def finalise = FinalPlaceSpec(num.get, name.get, pos.get, namePos, meaning, meaningPos, initialMarking.getOrElse(0), currentMarking.getOrElse(0), capacity, reference, entry, exit, blocks) } @@ -101,13 +104,15 @@ object LlnetParser extends Parsers with RegexParsers { } - case class ArcSpec ( producer: Option[Boolean] = None, from: Option[Int] = None, to: Option[Int] = None, weight: Option[Int] = None, weightPos: Option[(Int,Int)] = None, + case class ArcSpec ( from: Option[Int] = None, to: Option[Int] = None, weight: Option[Int] = None, weightPos: Option[(Int,Int)] = None, visibility: Option[Int] = None, anchorPoint: Option[(Int,Int)] = None ) { def + (other: ArcSpec) = - ArcSpec( producer + other.producer, from + other.from, - to + other.to, weight + other.weight, weightPos + other.weightPos, - visibility + other.visibility, anchorPoint + other.anchorPoint) + ArcSpec( from + other.from, to + other.to, weight + other.weight, + weightPos + other.weightPos, visibility + other.visibility, + anchorPoint + other.anchorPoint) + + def finalise = FinalArcSpec (from.get, to.get, weight.getOrElse(1), weightPos, visibility, anchorPoint) } case class BlockSpec ( num: Option[Int] = None, name: Option[String] = None, pos: Option[(Int,Int)] = None, @@ -127,7 +132,7 @@ object LlnetParser extends Parsers with RegexParsers { val EOI: Parser[Any] = new Parser[Any] { def apply(in: Input) = { if (in.atEnd) new Success( "EOI", in ) - else Failure("End of Input expected", in) + else Failure("end of file expected", in) } } @@ -141,19 +146,19 @@ object LlnetParser extends Parsers with RegexParsers { def str = "\".*?\"".r - def header = ("PEP" ~ (endofline) ~ ("PetriBox"|"PTNet") ~ (endofline) ~ "FORMAT_N") ~> integer <~ (endofline) + def header = ("PEP" ~ (endofline) ~ ("PetriBox"|"PTNet") ~ (endofline) ~ "FORMAT_N") ~> opt(integer) <~ (endofline) ^^ (_.getOrElse(1)) def fixedSpecs = (opt(integer) ~ opt (str) ~ position) def placeSpec = fixedSpecs flatMap { - case num_ ~ name_ ~ pos_ => placeOptSpec ^^ (PlaceSpec (num = num_, name = name_, pos = Some(pos_)) + _) + case num_ ~ name_ ~ pos_ => placeOptSpec ^^ (PlaceSpec (num = num_, name = name_, pos = Some(pos_)) + _) } - def placeOptSpec: Parser[PlaceSpec] = - ( ("n" ~> position) flatMap ( pos => placeOptSpec ^^ (PlaceSpec(namePos = Some(pos)) + _)) ) | + def placeOptSpec: Parser[PlaceSpec] = + ( ("n" ~> position) flatMap ( pos => placeOptSpec ^^ (PlaceSpec(namePos = Some(pos))+ _)) ) | ( ("b" ~> str) flatMap ( s => placeOptSpec ^^ (PlaceSpec(meaning = Some(s)) + _) )) | ( ("a" ~> position) flatMap ( pos => placeOptSpec ^^ (PlaceSpec(meaningPos = Some(pos)) + _)) ) | - ( ("M" ~> integer) flatMap ( im => placeOptSpec ^^ (PlaceSpec(initialMarking = Some(im)) + _)) ) | + ( ("M" ~> integer) flatMap ( im => placeOptSpec ^^ (PlaceSpec(initialMarking = Some(im)) + _))) | ( ("m" ~> integer) flatMap ( m => placeOptSpec ^^ (PlaceSpec(currentMarking = Some(m)) + _)) ) | ( ("k" ~> integer) flatMap ( c => placeOptSpec ^^ (PlaceSpec(capacity = Some(c)) + _)) ) | ( ("R" ~> str) flatMap ( s => placeOptSpec ^^ (PlaceSpec(reference = Some(s)) + _)) ) | @@ -189,9 +194,10 @@ object LlnetParser extends Parsers with RegexParsers { def transitions = ("TR" ~ endofline) ~> (transitionSpec+) - def consumerArcSpec = ((integer <~ ">") ~ integer) flatMap { case from ~ to => arcOptSpec ^^ (ArcSpec (Some(false), Some(from), Some(to)) + _) } + def consumerArcSpec = ((integer <~ ">") ~ integer) flatMap { case from ~ to => arcOptSpec ^^ (ArcSpec (Some(from), Some(to)) + _) } - def producerArcSpec = ((integer <~ "<") ~ integer) flatMap { case to ~ from => arcOptSpec ^^ (ArcSpec (Some(true), Some(from), Some(to)) + _) } + // this makes no sense! why use '<' and '>' if they don't actually show the arc direction? + def producerArcSpec = ((integer <~ "<") ~ integer) flatMap { case from ~ to => arcOptSpec ^^ (ArcSpec (Some(from), Some(to)) + _) } def arcOptSpec: Parser[ArcSpec] = ( ("w" ~> integer) flatMap ( w => arcOptSpec ^^ (ArcSpec(weight = Some(w)) + _)) ) | @@ -223,33 +229,80 @@ object LlnetParser extends Parsers with RegexParsers { def blocks = ("BL" ~ endofline) ~> (blockSpec+) - def text = (("TX" ~ endofline) ~> ("N" ~> position ~ str)+) ^^ (_.map { case pos ~ text => Text(pos, text) }) + def text = (("TX" ~ endofline) ~> ("N" ~> position ~ str <~ endofline)+) ^^ (_.map { case pos ~ text => Text(pos, text) }) def withAutoNum[A] (elements: List[A], nameBase: String)(implicit hasNum: HasNumName[A]) = elements.zipWithIndex.map { case (element, index) => hasNum.auto(element, (index+1), nameBase+(index+1)) } - def llnet = header ~ opt(blockDefaults) ~ opt(placeDefaults) ~ opt(transitionDefaults) ~ - opt(arcDefaults) ~ blocks ~ places ~ transitions ~ producerArcs ~ consumerArcs ~ opt(text) ^^ - { case format ~ blockDefaults ~ placeDefaults ~ transitionDefaults ~ - arcDefaults ~ blocks ~ places ~ transitions ~ producerArcs ~ consumerArcs ~ text => { - val blocksWithDefaults = if (blockDefaults.isDefined) blocks.map (blockDefaults.get + _) else blocks + def formatN1 = opt(placeDefaults) ~ opt(transitionDefaults) ~ + opt(arcDefaults) ~ places ~ transitions ~ producerArcs ~ consumerArcs ~ opt(text) ^^ + { case placeDefaults ~ transitionDefaults ~ + arcDefaults ~ places ~ transitions ~ producerArcs ~ consumerArcs ~ text => { val placesWithDefaults = if (placeDefaults.isDefined) places.map (placeDefaults.get + _) else places val transitionsWithDefaults = if (transitionDefaults.isDefined) transitions.map (transitionDefaults.get + _) else transitions val producerArcsWithDefaults = if (arcDefaults.isDefined) producerArcs.map(arcDefaults.get + _) else producerArcs val consumerArcsWithDefaults = if (arcDefaults.isDefined) consumerArcs.map(arcDefaults.get + _) else consumerArcs - Llnet (format, withAutoNum(blocksWithDefaults, "block").map(_.finalise), withAutoNum(placesWithDefaults, "p").map(_.finalise), - withAutoNum(transitionsWithDefaults, "t").map(_.finalise), producerArcsWithDefaults, consumerArcsWithDefaults) + Llnet (1, List(), withAutoNum(placesWithDefaults, "p").map(_.finalise), + withAutoNum(transitionsWithDefaults, "t").map(_.finalise), producerArcsWithDefaults.map(_.finalise), consumerArcsWithDefaults.map(_.finalise)) } } - def parseLlnet(file: File) = parse(phrase(llnet), (new BufferedReader(new FileReader(file)))) match { - case Success(r, _) => Right(r) - case err => Left(err.toString) + def formatN2 = failure ("FORMAT_N2 is not supported") + + def llnet = header flatMap { + case 1 => formatN1 + case 2 => formatN2 + case 3 => failure ("Expected FORMAT_N or FORMAT_N2") } + + def parseLlnet(file: File) = + ioPure.pure { + parse(phrase(llnet), (new BufferedReader(new FileReader(file)))) match { + case Success(r, _) => Right(r) + case err => Left(err.toString) + } + } + } -object Test extends App { - println("""(?m)\n""".matches("\n")) - println(LlnetParser.parseLlnet(new File("e:/tmp/llnet2"))) -} \ No newline at end of file + +object PetriNetBuilder { + import LlnetParser._ + import PetriNet._ + def buildPetriNet (llnet: Llnet): IO[VisualPetriNet] = { + for { + places <- llnet.places.traverse(p => newPlace.map((p.num, p.name, p.initialMarking, p.pos, _))); + val placeMap = places.map ( p => (p._1, p._5)).toMap; + transitions <- llnet.transitions.traverse (t => newTransition.map ((t.num, t.name, t.pos, _ ))); + val transitionMap = transitions.map( t => (t._1, t._4)).toMap; + parcs <- llnet.producerArcs.traverse ( a => newProducerArc ( transitionMap(a.from), placeMap(a.to) ) ) + carcs <- llnet.consumerArcs.traverse ( a => newConsumerArc ( placeMap(a.from), transitionMap(a.to) ) ) + } yield { + + val scale = 20 + + val netWithPlaces = places.foldLeft(VisualPetriNet.Empty) { + case (VisualPetriNet(net, layout, varcs), (num, name, marking, pos, place)) => + VisualPetriNet (net.copy (places = place :: net.places, labelling = net.labelling + (place -> name), + marking = net.marking + (place -> marking)), + layout + (place -> new Point2D.Double (pos._1.toDouble / scale, pos._2.toDouble / scale)), + varcs) + } + + val netWithTransitions = transitions.foldLeft(netWithPlaces) { + case (VisualPetriNet(net, layout, varcs), (num, name, pos, t)) => + VisualPetriNet(net.copy (transitions = t :: net.transitions, labelling = net.labelling + (t -> name)), + layout + (t -> new Point2D.Double (pos._1.toDouble / scale, pos._2.toDouble / scale)), + varcs) + } + + (parcs ++ carcs).foldLeft(netWithTransitions) { + case (VisualPetriNet(net, layout, varcs), arc) => + VisualPetriNet(net.copy (arcs = arc :: net.arcs), + layout, + varcs + (arc -> new Polyline(List()))) + } + } + } +} diff --git a/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/Module.scala b/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/Module.scala index 67664240..49f3166b 100644 --- a/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/Module.scala +++ b/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/Module.scala @@ -19,7 +19,7 @@ object PetriNetServiceProvider extends GlobalServiceProvider { def implementations[T](service: Service[GlobalScope, T]) = service match { case NewModelService => List(NewPetriNet) case ExporterService => List(PnExporter) - case FileOpenService => List(PnFileOpen) + case FileOpenService => List(PnFileOpen, LlnetFileOpen) case _ => Nil } } diff --git a/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/PetriNet.scala b/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/PetriNet.scala index 038a1251..2de165e5 100644 --- a/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/PetriNet.scala +++ b/PetriNetPlugin2/src/main/scala/org/workcraft/plugins/petri2/PetriNet.scala @@ -1,5 +1,6 @@ package org.workcraft.plugins.petri2 import java.awt.geom.Point2D +import org.workcraft.dom.visual.connections.Polyline import org.workcraft.scala.effects.IO import org.workcraft.scala.effects.IO._ import org.workcraft.dom.visual.connections.StaticVisualConnectionData @@ -75,4 +76,11 @@ case class VisualPetriNet(net: PetriNet, layout: Map[Component, Point2D.Double], object VisualPetriNet { val Empty = VisualPetriNet(PetriNet.Empty, Map(), Map()) -} \ No newline at end of file + + def withDefaultLayout (net: PetriNet): VisualPetriNet = + VisualPetriNet ( + net, + (net.places ++ net.transitions).foldLeft(Map[Component, Point2D.Double]())( (map, place) => map + (place -> new Point2D.Double(0,0))), + net.arcs.foldLeft(Map[Arc, StaticVisualConnectionData]()) ( (map, arc) => map + (arc -> new Polyline(List()))) + ) +} diff --git a/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/DotGFileOpen.scala b/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/DotGFileOpen.scala index 19cfe4fe..57e0fa6f 100644 --- a/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/DotGFileOpen.scala +++ b/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/DotGFileOpen.scala @@ -1,10 +1,14 @@ package org.workcraft.plugins.petrify import java.io.File +import org.workcraft.plugins.petri2.EditablePetriNet +import org.workcraft.plugins.petri2.PetriNetModel import org.workcraft.plugins.petri2.PnFormatParser +import org.workcraft.plugins.petri2.VisualPetriNet import org.workcraft.services.FileOpen import org.workcraft.services.FileOpenJob import org.workcraft.services.Format import org.workcraft.scala.effects.IO._ +import scalaz.Scalaz._ object DotGFileOpen extends FileOpen { val description = "Workcraft .g format importer" @@ -15,9 +19,11 @@ object DotGFileOpen extends FileOpen { override def open(file: File) = checkFile(file).map( if (_) Some(FileOpenJob( - DotGParser.parseDotG (file).map { - case Left(error) => Left(error) - case Right(dotg) => PetriNetBuilder.buildPetriNet(dotg).map(pn => Right(new PetriNetModel(n)))}.join)) - else + DotGParser.parseDotG(file) >>= { + case Left(error) => ioPure.pure { Left(error) } + case Right(dotg) => PetriNetBuilder.buildPetriNet(dotg) >>= + (pn => EditablePetriNet.create(VisualPetriNet.withDefaultLayout(pn)).map( epn => Right( new PetriNetModel (epn)))) + })) + else None) } diff --git a/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/DotGParser.scala b/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/DotGParser.scala index 56fbba36..cd489b99 100644 --- a/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/DotGParser.scala +++ b/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/DotGParser.scala @@ -96,9 +96,9 @@ object DotGParser extends Parsers with RegexParsers { def outputs = (".outputs" ~> (name+) <~ (emptyline+)) ^^ (s => DotG(outputs = s)) def internal = (".internal" ~> (name+) <~ (emptyline+)) ^^ (s => DotG(internal = s)) - def m = (placeRef ~ (("=" ~> number)?)) ^^ { case a ~ b => (a -> b.getOrElse(0)) } + def m = log((placeRef ~ (("=" ~> number)?)) ^^ { case a ~ b => (a -> b.getOrElse(1)) })("placeRef") - def implicitPlaceRef = "<" ~> (graphElement <~ ",") ~ graphElement <~ ">" ^^ { case from ~ to => ImplicitPlace(from, to) } + def implicitPlaceRef = log( "<" ~> (graphElement <~ ",") ~ graphElement <~ ">" ^^ { case from ~ to => ImplicitPlace(from, to) })("implicitPlaceRef") def placeRef = implicitPlaceRef | (name ^^ (ExplicitPlace(_))) @@ -125,8 +125,8 @@ object DotGParser extends Parsers with RegexParsers { } object Test extends App { - DotGParser.parseDotG(new File("e:/winpetrify/stgshka.g")) match { - case Left(err) => println(err) - case Right(dotg) => println(PetriNetBuilder.buildPetriNet(dotg).unsafePerformIO) - } + (DotGParser.parseDotG(new File("e:/winpetrify/stgshka.g")) >>= { + case Left(err) => ioPure.pure { println(err) } + case Right(dotg) => PetriNetBuilder.buildPetriNet(dotg).map(println(_)) + }).unsafePerformIO } diff --git a/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/Module.scala b/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/Module.scala index c3757221..ddd5ad2a 100644 --- a/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/Module.scala +++ b/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/Module.scala @@ -23,6 +23,7 @@ object PetrifyServiceProvider extends GlobalServiceProvider { def implementations[T](service: Service[GlobalScope, T]) = service match { case ExporterService => List(DotGExporter) case GuiToolService => List(StateGraphTool) + case FileOpenService => List(DotGFileOpen) case _ => Nil } } diff --git a/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/PetriNetBuilder.scala b/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/PetriNetBuilder.scala index 9a49fc85..29c4944f 100644 --- a/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/PetriNetBuilder.scala +++ b/PetrifyPlugin2/src/main/scala/org/workcraft/plugins/petrify/PetriNetBuilder.scala @@ -137,6 +137,9 @@ object PetriNetBuilder { } } - applyMarking + applyMarking.map ( net => { + val markingWithDefaultZeroes = net.places.foldLeft (net.marking) ( (marking, place) => if (!marking.contains(place)) marking + (place -> 0) else marking) + net.copy (marking = markingWithDefaultZeroes) + }) } } diff --git a/ScalaGraphEditorUtil/src/main/scala/org/workcraft/gui/modeleditor/sim/GenericSimulationTool.scala b/ScalaGraphEditorUtil/src/main/scala/org/workcraft/gui/modeleditor/sim/GenericSimulationTool.scala index e5870bd4..f3aaad85 100644 --- a/ScalaGraphEditorUtil/src/main/scala/org/workcraft/gui/modeleditor/sim/GenericSimulationTool.scala +++ b/ScalaGraphEditorUtil/src/main/scala/org/workcraft/gui/modeleditor/sim/GenericSimulationTool.scala @@ -1,4 +1,6 @@ package org.workcraft.gui.modeleditor.sim +import java.util.TimerTask +import javax.swing.SwingUtilities import org.workcraft.scala.effects.IO._ import org.workcraft.scala.Expressions._ @@ -23,7 +25,7 @@ import org.workcraft.gui.modeleditor.tools.ToolEnvironment import org.workcraft.scala.effects.IO import javax.swing.JPanel import javax.swing.JLabel -import javax.swing.Timer +import java.util.Timer import java.awt.event.ActionEvent import java.awt.event.ActionListener @@ -110,11 +112,14 @@ object GenericSimulationTool { val t = Variable.create(0.0) - new Timer(30, new ActionListener { - def actionPerformed(e: ActionEvent) = t.set(scala.math.sin(System.currentTimeMillis() / 200.0)).unsafePerformIO - }).start() + // new Timer(30, new ActionListener { + // def actionPerformed(e: ActionEvent) = t.set(scala.math.sin(System.currentTimeMillis() / 200.0)).unsafePerformIO + // }).start() + +// val tt = new Timer(true) +// tt.scheduleAtFixedRate(new TimerTask { def run =SwingUtilities.invokeLater ( new Runnable { def run = t.set(scala.math.sin(System.currentTimeMillis() / 200.0)).unsafePerformIO })}, 0, 30) val col = t.map(t => Colorisation(Some(new Color(80 + (40 * t).toInt, 200 + (40 * t).toInt, 80 + (40 * t).toInt)), None)) val highlightedColorisation = Colorisation(Some(new Color(240, 180, 40)), None) -} \ No newline at end of file +} diff --git a/Workcraft/src/main/scala/org/workcraft/DefaultConfiguration.scala b/Workcraft/src/main/scala/org/workcraft/DefaultConfiguration.scala new file mode 100644 index 00000000..1ee8629e --- /dev/null +++ b/Workcraft/src/main/scala/org/workcraft/DefaultConfiguration.scala @@ -0,0 +1,21 @@ +package org.workcraft + +import org.workcraft.plugins.petri2.PetriNetModule +import org.workcraft.plugins.petrify.PetrifyModule +import org.workcraft.plugins.lola.LolaModule +import org.workcraft.plugins.fsm.FSMModule +import org.workcraft.plugins.dot.DotModule +import org.workcraft.services.GlobalServiceManager +import java.io.File + +object DefaultConfiguration { + + val services = new GlobalServiceManager( + List(new PetriNetModule, new PetrifyModule, + new FSMModule, new LolaModule, new DotModule )) + + + def main (args: Array[String]) = { + org.workcraft.gui.Main.main ("default configuration", services, args) + } +} diff --git a/project/Build.scala b/project/Build.scala index beb34e3e..40a6c1fc 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -31,7 +31,7 @@ object Workcraft extends Build { .dependsOn (logger) lazy val core = Project(id = "core", base = file ("Core")) - .dependsOn (pluginManager, tasks) + .dependsOn (tasks) lazy val graphics = Project(id = "graphics", base = file("Graphics")) .dependsOn (scalautil, booleanFormulae) @@ -44,9 +44,12 @@ object Workcraft extends Build { lazy val gui = Project(id = "gui", base = file ("Gui")) .settings (libraryDependencies := Seq ( "org.streum" %% "configrity" % "0.9.0", "org.apache.xmlgraphics" % "batik-svg-dom" % "1.7", "org.apache.xmlgraphics" % "batik-svggen" % "1.7", "org.apache.xmlgraphics" % "batik-bridge" % "1.7", "tablelayout" % "TableLayout" % "20050920", "org.flexdock" % "flexdock" % "1.1.1", - "commons-logging" % "commons-logging" % "1.1", "org.pushingpixels" % "substance" % "6.1") + "commons-logging" % "commons-logging" % "1.1", "com.github.insubstantial" % "substance" % "7.1", "com.github.insubstantial" % "trident" % "7.1") , resolvers := repos) - .dependsOn (core, graphics) + .dependsOn (core, graphics, logger) + .settings (resourceDirectory in Compile <<= baseDirectory { _ / "src" / "main" / "resources" }) + .settings (scalacOptions ++= Seq("-unchecked", "-deprecation")) + lazy val pnplugin = Project (id = "pnplugin", base = file ("PetriNetPlugin2")) .dependsOn (gui, graphedutil) diff --git a/sbt.bat b/sbt.bat index 0bd6baa3..46687242 100644 --- a/sbt.bat +++ b/sbt.bat @@ -1,2 +1,2 @@ set SCRIPT_DIR=%~dp0 -java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx1024M -Xss2M -jar "%SCRIPT_DIR%\sbt-launch.jar" %* +java -Djline.terminal=jline.UnsupportedTerminal -Djline.WindowsTerminal.directConsole=false -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx1024M -Xss2M -jar "%SCRIPT_DIR%\sbt-launch.jar" %* diff --git a/sbt1.bat b/sbt1.bat new file mode 100644 index 00000000..0bd6baa3 --- /dev/null +++ b/sbt1.bat @@ -0,0 +1,2 @@ +set SCRIPT_DIR=%~dp0 +java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx1024M -Xss2M -jar "%SCRIPT_DIR%\sbt-launch.jar" %*