From 30ac48af1d53bae0cf0c112dc24126c743ece645 Mon Sep 17 00:00:00 2001 From: Matthew Aguirre Date: Wed, 21 Dec 2016 17:30:54 -0500 Subject: [PATCH 1/4] Updating the UI to use Docking Frames. --- pom.xml | 6 +- .../java/org/tros/torgo/ControllerBase.java | 140 +++++++++++++++--- .../java/org/tros/torgo/TorgoTextConsole.java | 5 +- .../tros/torgo/swing/TorgoUserInputPanel.java | 10 +- 4 files changed, 139 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index 876335e..fb140af 100644 --- a/pom.xml +++ b/pom.xml @@ -363,7 +363,11 @@ batik-anim 1.8 - + + org.dockingframes + docking-frames-common + 1.1.1 + junit junit diff --git a/src/main/java/org/tros/torgo/ControllerBase.java b/src/main/java/org/tros/torgo/ControllerBase.java index ec71ece..d4ee92d 100644 --- a/src/main/java/org/tros/torgo/ControllerBase.java +++ b/src/main/java/org/tros/torgo/ControllerBase.java @@ -15,19 +15,27 @@ */ package org.tros.torgo; +import bibliothek.gui.dock.DefaultDockable; +import bibliothek.gui.dock.common.CControl; +import bibliothek.gui.dock.common.CGrid; +import bibliothek.gui.dock.common.CLocation; +import bibliothek.gui.dock.common.DefaultSingleCDockable; +import bibliothek.gui.dock.common.mode.ExtendedMode; +import bibliothek.gui.dock.common.SingleCDockable; +import bibliothek.gui.dock.common.SingleCDockableFactory; +import bibliothek.util.xml.XElement; import org.tros.torgo.interpreter.CodeBlock; import org.tros.torgo.interpreter.InterpreterListener; import org.tros.torgo.interpreter.InterpreterThread; import org.tros.torgo.interpreter.Scope; import java.awt.BorderLayout; +import java.awt.Component; import java.awt.Container; import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -48,11 +56,11 @@ import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; -import javax.swing.JSplitPane; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.event.EventListenerSupport; +import org.apache.commons.lang3.tuple.ImmutablePair; import static org.tros.torgo.Main.IMAGE_ICON_CLASS_PATH; import org.tros.torgo.swing.AboutWindow; import org.tros.torgo.swing.Localization; @@ -157,6 +165,55 @@ protected ControllerBase() { */ protected abstract InterpreterThread createInterpreterThread(String source); + public class TorgoSingleDockable extends DefaultSingleCDockable { + + public TorgoSingleDockable(String title, final Component panel) { + super(title); + super.setTitleText(title); + super.add(panel); + } + } + + public class TorgoDockable extends DefaultDockable { + + public TorgoDockable(String title, final Component panel) { + super(title); + super.setTitleText(title); + super.add(panel); + } + } + + /* This method simulates the creation of a layout */ + private XElement createLayout(Component display, ArrayList> input) { + /* This method simulates the creation of a layout */ + CControl control = new CControl(); + control.getContentArea(); + + CGrid grid = new CGrid(control); + + DefaultSingleCDockable displayDock = display != null ? new TorgoSingleDockable("Display", display) : null; + if (displayDock != null) { + grid.add(0, 0, 10, 10, displayDock); + displayDock.setLocation(CLocation.base().minimalWest()); + displayDock.setExtendedMode(ExtendedMode.NORMALIZED); + } + + int count = 1; + for (ImmutablePair key : input) { + DefaultSingleCDockable green = new TorgoSingleDockable(key.left, key.right); + grid.add(10, 0, 6, count, green); + green.setExtendedMode(ExtendedMode.NORMALIZED); + count += 1; + } + + control.getContentArea().deploy(grid); + + XElement root = new XElement("root"); + control.writeXML(root); + control.destroy(); + return root; + } + /** * Initialize the window. This is called here from run() and not the * constructor so that the Service Provider doesn't load up all of the @@ -173,24 +230,71 @@ private void initSwing() { contentPane.add(tb, BorderLayout.NORTH); } - final java.util.prefs.Preferences prefs = java.util.prefs.Preferences.userNodeForPackage(NamedWindow.class); +// SplitDockStation station = new SplitDockStation(); +// DockFrontend frontend = new DockFrontend(window); +// frontend.addRoot("station", station); +// window.add(station); +// +// /* The Perspective object is needed to convert the layout to the perspective-format. */ +// DockFrontendPerspective perspective = frontend.getPerspective(false); +// /* And trough the Perspective object we can directly access the root stations. */ +// SplitDockPerspective stationPerspective = (SplitDockPerspective) perspective.getRoot("station"); +// +// /* We are now creating the representation of the Dockables we are later going to add */ +// PerspectiveDockable dockableRed = torgoCanvas != null ? new FrontendDockablePerspective("Display") : null; +// PerspectiveDockable dockableGreen = new FrontendDockablePerspective("Input"); +// PerspectiveDockable dockableBlue = new FrontendDockablePerspective("Output"); +// /* Then we put two dockables in the same stack. */ +// StackDockPerspective stack = new StackDockPerspective(new PerspectiveDockable[]{dockableGreen, dockableBlue}, dockableGreen); +// /* The SplitDockStation internally uses a tree to represents its layout, here we create such a tree */ +// SplitDockPerspective.Leaf childRed = new SplitDockPerspective.Leaf(dockableRed, null, null, -1); +//// SplitDockPerspective.Leaf childGreen = new SplitDockPerspective.Leaf( dockableGreen, null, null, -1 ); +//// SplitDockPerspective.Leaf childBlue = new SplitDockPerspective.Leaf( dockableBlue, null, null, -1 ); +// SplitDockPerspective.Leaf childStack = new SplitDockPerspective.Leaf(stack, null, null, -1); +// SplitDockPerspective.Node node = new SplitDockPerspective.Node(Orientation.HORIZONTAL, 0.4, childRed, childStack, null, null, -1); +// stationPerspective.getRoot().setChild(node); +// +// if (dockableRed != null) { +// frontend.addDockable("Display", new TorgoDockable("Display", torgoCanvas.getComponent())); +// } +// for(ImmutablePair pair : torgoPanel.getTorgoComponents()) { +// frontend.addDockable(pair.left, new TorgoDockable(pair.left, pair.right)); +// } +// /* Finally the perspective is applied to the DockFrontend */ +// perspective.apply(); + + CControl control = new CControl(window); + window.add(control.getContentArea(), BorderLayout.CENTER); + final ArrayList presetFilter = new ArrayList<>(); if (torgoCanvas != null) { - final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, torgoCanvas.getComponent(), torgoPanel.getComponent()); - int dividerLocation = prefs.getInt(this.getClass().getName() + "divider-location", window.getWidth() - 300); - splitPane.setDividerLocation(dividerLocation); - splitPane.addPropertyChangeListener(new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent pce) { - prefs.putInt(this.getClass().getName() + "divider-location", splitPane.getDividerLocation()); - } - }); - - contentPane.add(splitPane); - } else { - contentPane.add(torgoPanel.getComponent()); + presetFilter.add("Display"); + } + for(ImmutablePair pair : torgoPanel.getTorgoComponents()) { + presetFilter.add(pair.left); } + bibliothek.util.Filter filter = new bibliothek.util.Filter() { + @Override + public boolean includes(String item) { + return presetFilter.contains(item); + } + }; + control.addSingleDockableFactory(filter, new SingleCDockableFactory() { + @Override + public SingleCDockable createBackup(String id) { + if ("Display".equals(id)) { + return new TorgoSingleDockable(id, torgoCanvas.getComponent()); + } else { + for (ImmutablePair pair : torgoPanel.getTorgoComponents()) { + if (pair.left.equals(id)) { + return new TorgoSingleDockable(pair.left, pair.right); + } + } + } + return null; + } + }); + control.readXML(createLayout(torgoCanvas != null ? torgoCanvas.getComponent() : null, torgoPanel.getTorgoComponents())); JMenuBar mb = createMenuBar(); if (mb == null) { mb = new TorgoMenuBar(window, this); diff --git a/src/main/java/org/tros/torgo/TorgoTextConsole.java b/src/main/java/org/tros/torgo/TorgoTextConsole.java index 388e67e..db6a3f7 100644 --- a/src/main/java/org/tros/torgo/TorgoTextConsole.java +++ b/src/main/java/org/tros/torgo/TorgoTextConsole.java @@ -16,6 +16,9 @@ package org.tros.torgo; import java.awt.Component; +import java.util.ArrayList; +import java.util.Map; +import org.apache.commons.lang3.tuple.ImmutablePair; /** * I/O interface. Get source and print messages. @@ -98,5 +101,5 @@ public interface TorgoTextConsole { * * @return */ - Component getComponent(); + ArrayList> getTorgoComponents(); } diff --git a/src/main/java/org/tros/torgo/swing/TorgoUserInputPanel.java b/src/main/java/org/tros/torgo/swing/TorgoUserInputPanel.java index 81a0bd7..aff131d 100644 --- a/src/main/java/org/tros/torgo/swing/TorgoUserInputPanel.java +++ b/src/main/java/org/tros/torgo/swing/TorgoUserInputPanel.java @@ -18,12 +18,14 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.Font; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URL; +import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.ImageIcon; @@ -35,6 +37,7 @@ import javax.swing.text.DefaultHighlighter; import javax.swing.text.Highlighter; import javax.swing.text.LayeredHighlighter; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rtextarea.Gutter; import org.fife.ui.rtextarea.GutterIconInfo; @@ -347,7 +350,10 @@ public void highlight(int line, int startChar, int endChar) { * @return */ @Override - public Component getComponent() { - return this; + public ArrayList> getTorgoComponents() { + ArrayList> ret = new ArrayList<>(); + ret.add(new ImmutablePair("Input", tabs)); + ret.add(new ImmutablePair("Output", outputTextArea)); + return ret; } } From f460c3288388d6ec94b04edf7dd0517d8e4ef6e8 Mon Sep 17 00:00:00 2001 From: Matthew Aguirre Date: Wed, 21 Dec 2016 19:22:14 -0500 Subject: [PATCH 2/4] Renamed some variables. Cleaned up TorgoUserInputPanel.java --- .../java/org/tros/torgo/ControllerBase.java | 8 ++-- .../tros/torgo/swing/TorgoUserInputPanel.java | 42 ++----------------- 2 files changed, 7 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/tros/torgo/ControllerBase.java b/src/main/java/org/tros/torgo/ControllerBase.java index d4ee92d..7e8fb5d 100644 --- a/src/main/java/org/tros/torgo/ControllerBase.java +++ b/src/main/java/org/tros/torgo/ControllerBase.java @@ -200,9 +200,9 @@ private XElement createLayout(Component display, ArrayList key : input) { - DefaultSingleCDockable green = new TorgoSingleDockable(key.left, key.right); - grid.add(10, 0, 6, count, green); - green.setExtendedMode(ExtendedMode.NORMALIZED); + DefaultSingleCDockable dock = new TorgoSingleDockable(key.left, key.right); + grid.add(10, 0, 6, count, dock); + dock.setExtendedMode(ExtendedMode.NORMALIZED); count += 1; } @@ -293,8 +293,8 @@ public SingleCDockable createBackup(String id) { return null; } }); - control.readXML(createLayout(torgoCanvas != null ? torgoCanvas.getComponent() : null, torgoPanel.getTorgoComponents())); + JMenuBar mb = createMenuBar(); if (mb == null) { mb = new TorgoMenuBar(window, this); diff --git a/src/main/java/org/tros/torgo/swing/TorgoUserInputPanel.java b/src/main/java/org/tros/torgo/swing/TorgoUserInputPanel.java index aff131d..efe7e02 100644 --- a/src/main/java/org/tros/torgo/swing/TorgoUserInputPanel.java +++ b/src/main/java/org/tros/torgo/swing/TorgoUserInputPanel.java @@ -18,10 +18,7 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; -import java.awt.Dimension; import java.awt.Font; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URL; @@ -29,9 +26,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.ImageIcon; -import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultHighlighter; @@ -48,15 +43,12 @@ import org.tros.torgo.interpreter.Scope; import org.tros.torgo.TorgoTextConsole; -public abstract class TorgoUserInputPanel extends JPanel implements TorgoTextConsole { +public abstract class TorgoUserInputPanel implements TorgoTextConsole { private final RSyntaxTextArea inputTextArea; - private final RTextScrollPane scrollPane; private final Gutter gutter; private final JConsole outputTextArea; - private final JSplitPane splitPane; - private final JPanel inputTab; private final JTabbedPane tabs; public static final String DEBUG_ICON = "debugging/breakpointsView/Breakpoint.png"; @@ -76,20 +68,18 @@ public abstract class TorgoUserInputPanel extends JPanel implements TorgoTextCon @SuppressWarnings("OverridableMethodCallInConstructor") public TorgoUserInputPanel(Controller controller, String name, boolean editable, String syntax) { this.controller = controller; - BorderLayout layout = new BorderLayout(); - setLayout(layout); defaultHighlighter = DefaultHighlighter.DefaultPainter; breakpointHighlighter = new DefaultHighlighter.DefaultHighlightPainter(Color.PINK); //SOURCE - inputTab = new JPanel(); + JPanel inputTab = new JPanel(); inputTab.setLayout(new BorderLayout()); inputTextArea = new org.fife.ui.rsyntaxtextarea.RSyntaxTextArea(); inputTextArea.setAntiAliasingEnabled(true); inputTextArea.setCodeFoldingEnabled(true); inputTextArea.setSyntaxEditingStyle(syntax); - scrollPane = new org.fife.ui.rtextarea.RTextScrollPane(inputTextArea); + RTextScrollPane scrollPane = new org.fife.ui.rtextarea.RTextScrollPane(inputTextArea); scrollPane.setIconRowHeaderEnabled(true); gutter = scrollPane.getGutter(); try { @@ -108,35 +98,9 @@ public TorgoUserInputPanel(Controller controller, String name, boolean editable, tabs = new JTabbedPane(); tabs.add(name, inputTab); - JPanel output = new JPanel(); - BorderLayout outputLayout = new BorderLayout(); - output.setLayout(outputLayout); outputTextArea = new JConsole(); -// outputTextArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); outputTextArea.setEditable(editable); -// JScrollPane outputScrollPane = new JScrollPane(outputTextArea); - - JLabel messagesLabel = new JLabel(Localization.getLocalizedString("MessagesLabel")); - JPanel messages = new JPanel(); - messages.setLayout(new BorderLayout()); - messages.add(messagesLabel, BorderLayout.PAGE_START); - messages.add(outputTextArea, BorderLayout.CENTER); - output.add(messages, BorderLayout.CENTER); - - splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tabs, output); - final java.util.prefs.Preferences prefs = java.util.prefs.Preferences.userNodeForPackage(TorgoUserInputPanel.class); - int dividerLocation = prefs.getInt(TorgoUserInputPanel.class.getName() + "divider-location", 0); - dividerLocation = dividerLocation == 0 ? 400 : dividerLocation; - splitPane.setDividerLocation(dividerLocation); - splitPane.addPropertyChangeListener(new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent pce) { - prefs.putInt(TorgoUserInputPanel.class.getName() + "divider-location", splitPane.getDividerLocation()); - } - }); - this.add(splitPane); controller.addInterpreterListener(new InterpreterListener() { From 4ab4059aa08e7392013f0049a36823118141915d Mon Sep 17 00:00:00 2001 From: Matthew Aguirre Date: Wed, 21 Dec 2016 19:57:35 -0500 Subject: [PATCH 3/4] Added icons to the dockable windows. --- .../java/org/tros/torgo/ControllerBase.java | 12 +++++++++--- src/main/java/org/tros/torgo/Main.java | 13 +++++++++++-- src/main/resources/display-24x24.png | Bin 0 -> 438 bytes src/main/resources/display-512x512.png | Bin 0 -> 1830 bytes src/main/resources/input-24x24.png | Bin 0 -> 3027 bytes src/main/resources/input-512x512.png | Bin 0 -> 6342 bytes src/main/resources/output-24x24.png | Bin 0 -> 1055 bytes src/main/resources/output-512x512.png | Bin 0 -> 16653 bytes 8 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 src/main/resources/display-24x24.png create mode 100644 src/main/resources/display-512x512.png create mode 100644 src/main/resources/input-24x24.png create mode 100644 src/main/resources/input-512x512.png create mode 100644 src/main/resources/output-24x24.png create mode 100644 src/main/resources/output-512x512.png diff --git a/src/main/java/org/tros/torgo/ControllerBase.java b/src/main/java/org/tros/torgo/ControllerBase.java index 7e8fb5d..644b65d 100644 --- a/src/main/java/org/tros/torgo/ControllerBase.java +++ b/src/main/java/org/tros/torgo/ControllerBase.java @@ -281,16 +281,22 @@ public boolean includes(String item) { control.addSingleDockableFactory(filter, new SingleCDockableFactory() { @Override public SingleCDockable createBackup(String id) { + TorgoSingleDockable ret = null; if ("Display".equals(id)) { - return new TorgoSingleDockable(id, torgoCanvas.getComponent()); + ret = new TorgoSingleDockable(id, torgoCanvas.getComponent()); } else { for (ImmutablePair pair : torgoPanel.getTorgoComponents()) { if (pair.left.equals(id)) { - return new TorgoSingleDockable(pair.left, pair.right); + ret = new TorgoSingleDockable(pair.left, pair.right); } } } - return null; + if(ret != null) { + //TODO: find good icons for this.... + ImageIcon icon = Main.getIcon(ret.getTitleText().toLowerCase() + "-24x24.png"); + ret.setTitleIcon(icon); + } + return ret; } }); control.readXML(createLayout(torgoCanvas != null ? torgoCanvas.getComponent() : null, torgoPanel.getTorgoComponents())); diff --git a/src/main/java/org/tros/torgo/Main.java b/src/main/java/org/tros/torgo/Main.java index 231b84a..252ffcc 100644 --- a/src/main/java/org/tros/torgo/Main.java +++ b/src/main/java/org/tros/torgo/Main.java @@ -199,12 +199,21 @@ public void run() { public static final String IMAGE_ICON_CLASS_PATH = "torgo-48x48.png"; public static void loadIcon(Window frame) { + frame.setIconImage(getIcon().getImage()); + } + + public static ImageIcon getIcon() { + return getIcon(IMAGE_ICON_CLASS_PATH); + } + + public static ImageIcon getIcon(String path) { try { - java.util.Enumeration resources = ClassLoader.getSystemClassLoader().getResources(IMAGE_ICON_CLASS_PATH); + java.util.Enumeration resources = ClassLoader.getSystemClassLoader().getResources(path); ImageIcon ico = new ImageIcon(resources.nextElement()); - frame.setIconImage(ico.getImage()); + return ico; } catch (IOException ex) { org.tros.utils.logging.Logging.getLogFactory().getLogger(Main.class).warn(null, ex); } + return null; } } diff --git a/src/main/resources/display-24x24.png b/src/main/resources/display-24x24.png new file mode 100644 index 0000000000000000000000000000000000000000..3cf679d515b7889ecf9421cc546e9be1c70982ff GIT binary patch literal 438 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbQ|Pfsr-9C&ZO;6fiQfI&Llmh6`g! zkY6x^!?PP{AWo9Ey9+}HtE>l*!&%@FSqu!y>mbbNq%pe!D9B#o>Fdh=fJcnMls{rl zw>wZs%hSa%MB{ui$6-c^4;}^y%!`G#OgkVbe_~a^3$;)u?xZbZ%aYbyOPa{QuzbJC VUh`wWc!9bYJYD@<);T3K0RW=)FxdbA literal 0 HcmV?d00001 diff --git a/src/main/resources/display-512x512.png b/src/main/resources/display-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..55929b0dac5a77c655bc88b319eacb23fc9098d5 GIT binary patch literal 1830 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&w@L)Zt|+Cx8@lv6E*A2M5RPhyD+MT+RZI z$YP-K>mbbNq%pe!C@5Lt8c`CQpH@mmtT}V`<;yx0|O&R zfKQ0)|Ns9PM*$<_L6J8{fdLm@666=mz{JeT&LbcqDk&u+ub`}|Ze(n3X=~@;aZS zZd$RR;~u3B1*_Jbs@~I5XP@J~@a^|MHQVKH*Q@(B^5wD}xvAamz`()4sKCI|z#zcD zL=1tFWhFa{R7q!WS93~`nY|II|M%1Y1k@>QAi^2rI|?ZubZm`A@oc62Sn zAtgienI20fA3ne9;_bA(S9jUuawaS&SDWj%)VNbzW?|@B^H*QjF|eIG@g*lKt!#~Y za_s!8Qt8jlnIuGnyI;26oG8a%Ra_QhpT)i4{<7!q{p#+!t(U#(e~$IS`jzL;oYztP zZP)uO@$Hgpq7Lh)|9umamz0opS#N&WEv6SY=NO+pJ=3w;;qpp3nULK~6@`z>r~iA> zaPIA=JjESC2fXindb)Y$!8)_sE5p2=GgSz#jH%NT5w_KxD$P`pcCsc<(dGKp!kt${ z4s4!zX1z}9+q9+CJK}eV959y9P1*eLkKeZ7l_LAO9%Me_ZvCjRXI`z zWqq9K$KuJ@VVD_UC<6{NG_fI~0ue<-1QkJoA_k0xBC#Thg@9ne9*`iQ#9$Or zQF$}6R&?d%y_c8YA7_1QpS|}zXYYO1x&V;8{kgn!SPFnNo`4_X6{c}T{8k*B#$jdxfFg<9uYy1K45IaYvHg`_dOZM)Sy63ve6hvv z1)yUy0P^?0*fb9UASvow`@mQCp^4`uNg&9uGcn1|&Nk+9SjOUl{-OWr@Hh0;_l(8q z{wNRKos+;6rV8ldy0Owz(}jF`W(JeRp&R{qi2rfmU!TJ;gp(Kmm5I1s5m_f-n#TRsj}B0%?E`vOzxB2#P=n*a3EfYETOrKoe*ICqM@{4K9Go;5xVgZi5G4 z1dM~{UdP6d+Yd3o?MrAqM0Kc|iV92owdyL5UC#5<>aVCa44|hpM4E zs0sQWIt5*Tu0n&*J!lk~f_{hI!w5`*sjxDv4V%CW*ah~3!{C*0BD@;TgA3v9a1~q+ zAA{TB3-ERLHar49hi4Ih5D^-ph8Q6X#0?2VqLBoIkE}zAkxHZUgRb+f=nat zP#6>iMMoK->`~sRLq)(kHo*Vn{;LcG6+edD1=7D>9j^O?D{Qg|tCDK{ym)H7&wDr6*;uGTJg8GHjVbnL{!cWyUB7MT6o-VNo_w8Yq`2<5Ub)hw4L3rj}5@qxMs0 zWMyP6Wy582WNT#4$d1qunl{acmP#w5ouJ*Jy_Zv#bCKi7ZIf$}8d zZdVy&)LYdbX%I9R8VMQ|8r>Q*nyQ)sn)#Z|n)kKvS`4iu ztvy=3T65Yu+7a4Yv^%sXb>ww?bn(=Yu(!=O6^iuTp>)p_Y^{w=i z^lS773}6Fm1Fpe-gF!>Ip{*g$u-szvGhed;vo5pW&GpS$<~8QGEXWp~7V9lKEnZq0SaK{6Sl+dwSOr*Z zvFf(^Xl-N7w{EeXveC4Ov)N}e%%C!Y7^RFWwrE>d+x51mZQt2h+X?JW*!^a2WS?Sx z)P8cQ&Qi|OhNWW;>JChYI)@QQx?`Nj^#uJBl~d&PK+RZLOLos~K(b5>qmrMN0})tOkySZ3_W zICNY@+|jrX%s^&6b2i>5eqa0y%Z;^%^_=a@u3%4b9605ii3Ep)@`TAmhs0fpQ%O!q zl}XcFH*PieWwLj2ZSq`7V9Mc?h17`D)-+sNT-qs~3@?S(ldh7UlRlVXkWrK|vf6I- z?$tAVKYn8-l({mqQ$Q8{O!WzMg`0(=S&msXS#Pt$vrpzo=kRj+a`kh!z=6$;c zwT88(J6|n-WB%w`m$h~4pmp)YIh_ z3ETV2tjiAU!0h1dxU-n=E9e!)6|Z;4?!H=SSy{V>ut&IOq{_dl zbFb#!9eY1iCsp6Bajj|Hr?hX|zPbJE{X++w546-O*Ot`2Kgd0Jx6Z4syT zu9enWavU5N9)I?I-1m1*_?_rJ$vD~agVqoG+9++s?NEDe`%Fht$4F;X=in*dQ{7$m zU2Q)a|9JSc+Uc4zvS-T963!N$T{xF_ZuWe}`RNOZ7sk3{yB}PPym+f8xTpV;-=!;; zJuhGEb?H5K#o@~7t9DmUU1MD9xNd#Dz0azz?I)|B+WM{g+Xrk0I&awC=o(x)cy`EX z=)z6+o0o6-+`4{y+3mqQ%kSJBju{@g%f35#FZJHb`&swrA8dGtepviS>QUumrN{L@ z>;2q1Vm)$Z)P1z?N$8UYW2~{~zhwUMVZ87u`Dx{Z>O|9|`Q+&->FRy-Sjp7DHs zy69KwU-!MxeeuI@&cF4|M9z%AfP?@5 z`Tzg`fam}Kbua(`>RI+y?e7jT@qQ9J+u00v@9M??Vs0RI60puMM)00009a7bBm z000XU000XU0RWnu7ytkO2XskIMF-#v763LCj?*Fj0002qNklKJLIqu+em>L}POYhCmu~A4tf7!!QHy zpF3xUH$#qYvB4Yzv?OYZZRIcApq&Aq?ZAtFVv<%9@OmYKtXTGW-bCfKH%-E~ak|oD zDV{c2`Rw1oPq7?XEW_$Yl@5m`J}`+kEf(lwjr-{L@S0UQjN{{rYOIU540s!N0oc_Q zzW*9aQ3tDlJjU219`JccFG=MTsdg07!A{9( z975%g+LDlCp|&%7Cd|yYp3(bW`~BW)zu&(0_g>fc&*!?VHP5>5^}B!fegB@dp7Xn$ z>_i0D3jzQ{9PF)K0pNi@c>q5KP79&GEWt^DV()z#03iwF9|f|nNdqA0eALQn*RCT$ zXM#>238D}jtgHx>Q$YboPaFmy^h2&2+1+hoof+ffg5?ex_41A&*R}ivSIZ=-WZEV* z1p%?`G=&>IYhCKZZESe)E%`KbN(wc3t&6(w1;O{&QH7f+@waFfUM>$s+&ccQit)LP z{kYqFtYkj7tOHBu7rtt*=VCw=zH7Nbd@#Pbv1w>jlN2kcOaWs2Wrq|_vy@PP8EtC1 zMUjrJ0jSWoLi~WfGl#A%o5;a^vCQ&8QO~02XVQ#z@KYrLDLlop0FZ1^)ZENXZXll* z_`dQ#I0ANQ0AH1u&u;-WmzfoT0(&njtVQLg0fNL~nl(6L0!lh|U$6mQ+CVa3N24)# zuK~0jJOk{(gC~IAE++H{@CyTN7h1w*z#9R4Ta=VS!PzVzX*=g>I=iJ*Y)lPSD(jJH zg|e|t>|TD2V63O7<_6Vv2dOQRTm5+avPqitVOcV|vHG~d`Bnh()7HXl=UJicqNVNa zTT{wK4`_U;#c&i49voqR>L{j=02n$G-N{zhDqBxA!B9`KZ*H98J+faY{|81=z#|;# zG030z;5ko0YGZTbVnt8Sr_s^(+Z!$S`n~jwVw39+&^=ivzD1j^Fct@EhLvM=_r==r zG6(Bh7aVWPc3cuTd$8|ws@=*HAW%sljn7BE1tK!wE6kQ zH=IMm1M16Y^8o|!;FvioB2DAYK7aIYJ5z~NFb0Q;?#HQis95u5n|u+EQFdtiZIsFPNwV`S_2`s##Me7BypRBo)d6tfgO zM3p_|ySXIJQuSQh135KctzSrT`gE5g=h7*nn)Mz}Ma?LZ)l3tmbo{8Cv7Oocjo-Ze?egcmeP7sVZE2KG9x7u*RR_HuJ(r+ADLeQcklnX~}i zxRrBNb~=}1AGw(QBK+8@;*R0^v$i*dULQK6lbyOQKj-zSpVyluZ@n@0y7&n0L#nw| zvo?KP8mrfMLR+(`!SbPzxKne%|y<{9B{+L0z3hFMD;RcWY85w8SE4 zR*i0&C$1Cuay4c!=dAku*R3w30qncMsr6S zM)gMVqY86-1#=IQf`4MV4Xe7oJholtlh`NyPng4*x)vU{vR(V{+;A5+NZn(3??$=n zeV4>L68b-68@I);bJ%hF-pwm-*B_BO!Z><={LC}){wo`tGG2SWc{O1-o-vMI2oV-J zw>G|+Mpl){k;Y1sWkRIyXF3+hyiJm6cGou4`IfnTl`dlcpF`s#*vBi}W-lUPK)6XZ_( zDcYNL9^>8M*x+pSlS}@?10z*U1R;N!vQTw}<08f9euy<_-1M-mC-O(N%1oAAWs+IZ z-5bVMdfW9p%UtI#2N1C%nZe9!XPgAaR0}iaqc41voZdXV8DF69SfO*+=XlZ8jH_P7 z_Qfv6c3-QvmQEJt7F63*dN0R{S~PE0@lmlOr?&Iuj=A-?^%n{juG?w0ZLw6d==g2? zjY{i~+Q7o8%)FZY)I7(a!jECqV@tA8S}b?g$)&{gdE{i%$);PIFq;%M?b!Kc=Tx@q z&WeJ~1tyLrj?HbYZ8zKAWf|m{>2&Lk<&5QY=L|gY-4nV;z5Gu3)58vrM)wqWPnA~% zChRfxzU}3)XJ47^z1({n-&NkLEEF%Sa7uS7&U;60craW3qWta?nFpWVV|q)=PnJjd zkq=6dpFA&Zm`blsk9rpMH+oX({vH%uih(F&{BC{HXiU`#`H9{YlG{SI!MVc?S{(tYVZnhdAM! zPEbhQh$5rU$6CbhpOKa3_?2ltWFPDFIiu;{+L77 zaW=lMvE4w;yh!ty=?BAS`p<|>ngQOeU0%6f4kvcV8f&VRZVfz9Gq5r_pE#U5EHn}! zm8sRTj}msHy?!B~aNS+aHR{{0k{oGHMwe$S#MJJrOWrsq5wbBwFsxp#o~)?VxwVt_ z-pWU9gVUV7+RpGxzou0ggegDQyRH7I;;hQui&c&yj{P~?^44YlNI0o$wyjzx{!-e- zV9O$fo$2M|FXYbwKfWqCobZVKJTU2r)`lzC7stykmhgFN2$owGjJxkq?N-A+A|Lh) zsBJs{()em|-j=q>*0Ptq7Y(mXU*}A&sb4d6sr>f29iAF;UZ1N=ju}5P4G!xS99he^ z<=k#eiRse|6jZ+S^Qs?mxLNxG%YHoqE&% z*sq%z*g1udsQOL+*RI~ZRScH-i<({!l*i7lfUd*K4$EZ>V(Iy!3Fg)1ll$&DoeZ9A zM!!L`uu7uk-4(xd$-OaicTIh_<*S`&vwRIZcREBvWUGkB->x+cD^aY&Mkg2o1B?wK z+dll598ofaeJlT?99d55m}T}{wr!4E_VV6?d!ISCns>hY@-ckHu2&v+P2bczZ2P?X zi=!VV;@+l{=Q@&eujEEWYkuqV?Y&tZG3MVsa10kT{Y>o4&>I_0(wIq=NxRS7(=&6A zdOt~cKK0DLzwN-uFK51(veVx>H&i)s1BQ5$9dP4 zXKdDAJs%##c+OZHSl1tYN`=+_s1CtQn!A@ID#aZ#CW~IJ5Cvxs z%&xE9?VXvOH!|ij(rZsf-e!HFf0eo4+f?7Qq2@)Xp3eS--OH18A$=io)3*k2&ZCip z7*)=ZZx0vUUKcK>%cQ4sc+r{jEB<;Kz3_XJ;BW7`6M*oI08rxr_{M?r1OPv11MtNc zfNhxoNCjOw@Z1)Dv(7qLTeydQ__fa^P@;#&#szVkT5ijj&P^O z|32|U+u46Cet-JINpyy?B7#B#(uxkRFaWcLyuz^z=4Ww0t0j-ZSbnGRFed{099@x! zLKes2;?ODlAe?3yKK;<<8i?*gT=E`6hJ>)s8Q&^dyntZ6vTMnKE&@qQtjI#>P6cKd zQvi@ogf`4M^8^CWczuw32mpSex{j9sh)Kp>&q4u$GB44DvxY#W&R7U>PUYia7!_vN zdH@bu%$zoWUtDp6W5)rYq3b$&;4Z$n>rdb=3@!Co_#Z4E$M_+{&7(hO5`YwEMS76paTZ3erFyySjoPrN% z$++nU&}Q^^$1?b!UWe4rYN&rJ09a+-fnYSCXj@){jUe(4z=SE%aY%s@>nnp`o;aka z@`3|sG)#|zhRN+>I!Qx-_*ExH17e50q7fx)wqT$gc9FDlW2RaMf?y31h=ge_`co8y zK#C^6sn+dxo-A0V@19688b*;ie8)sejY}VZrT88l3Wr8?jFuOHLAZ&;BgNAG#?t>M z5bo-O*<9G%-$BDwT5Tb~5BUEcZ&-^BQHOEKk+rD}3_Ldwt(J*66S)Q?T{J?N`malL zE7|5?Lr5mpYo#CYt7GD!CrKM>hDH=iu0=s)-jSgHH~pVfV^|(`fXYlF(qb;d89mHx z#D8dvXC@)w=;73V8UJb+s4=ELqO?CXB1(hj_x~``hy=DY6yskV5g`+}az;k@w)|C~ zKPEAZqY)wWe{39{-t5a|{YT>;Q~9GhA>^dF6#xAA?^1$w{PRHn-t&7HM2R@e|7L`T zR6J@hhK1m8f5RHSUJpt+7Aq*jRiij80fsKy&4J3p!($I#^WP73Vd~fUWg?9T&wsHP zI&y*wQ;q+zm3w~rg4SRbZWsq|f<}3G6U<^iW2j$apt}gvFn!B@)3|w2jVIy+cp#h7 z%lH`G@vYMEDk2Z7P_Y|Mh#DfHZYE|ZKoT9kpH-;E`yMWbaqkKv&@Tunp>~-y3Zo)} z0D2JpuJpBBGIE5U#n~q+596dkXG5zPox!IK`uL4Z#UaV3{ox#`ZHcNM_tF6c4^gGT z7JrTqE*%W9%zaB^oL9ZGXLRApM%&aEB0MY0wG!-?dyH zvlX_7pU3<-%tAFB!%U8?Kn*S(Ak6f@Zz3_l$O5>5vfw!5&2t(}U#z7J>hbmg0)hD} zq^>X_Go**+_Q9f#%=Z*U@|uxBVWsVi4q;E!y6s7k83QNm8 z6p?^6e}|klkj)!p@vVZ?mti2dV`$U&+tSG1Y;Q-`X}(piyF>H7>xLft#dt(!l@WEQ z2Nn$K0hX(nJQWru$PK}j3hDh!GUSO$3X$*)1W(yg#?E!8QGHO3NwBv@N1{aY_9RQC5?hlFw0RIU=S%u1 zad{Y`Xa%)sZIH}Wb0)4t9KKm=wKmjEE74Jb)blX5G>TTkL`RHG2VaX}?_azak{=;o zwFRaJ_d)}PDo!$98pipslg*b^s8{%n#%%^nP)|`536eGw(V8uFJTVMQJzuucdL8Vx zauKF->@P9VfuN+IWhZqU$xloMbyJH?`pKWn;@u_i!cyA$0P-$c2l604(9{-wv8Y+B zHc(U|Ej*VW>@vSLI}I-1n(rDCi=4$$&|(z=|Kw1+ZLWui;(r@vF?-^Pd(nv)$niyhQEBD!-s(1#6b;>qv_+otA;HV1!#RpJZtV6 z7DK;sp94AY7=kz)NJBxgGcVAC-rPk+?&j6SLDY;#HwR*+;URx29f==WkD@d!){dh| zqZk;Ipo{QPL?eVgOg-tH+*iwiRILM%WgawX29-aw4D8$!ZOrurA^`kzuyL|3we*eq EFTY=Ml>h($ literal 0 HcmV?d00001 diff --git a/src/main/resources/output-24x24.png b/src/main/resources/output-24x24.png new file mode 100644 index 0000000000000000000000000000000000000000..0b843b2206c556b27e4ce0dbbeb9c11cc27a1902 GIT binary patch literal 1055 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 Date: Thu, 22 Dec 2016 09:22:10 -0500 Subject: [PATCH 4/4] Updated Layout. Init layout has a better Input/Output display ratio. Can now save Layout on close. Can load saved Layout on open. --- .../java/org/tros/torgo/ControllerBase.java | 104 +++---- .../resources/{ => layouts}/display-24x24.png | Bin .../{ => layouts}/display-512x512.png | Bin .../resources/layouts/dynamic-logo-layout.xml | 272 ++++++++++++++++++ .../resources/{ => layouts}/input-24x24.png | Bin .../resources/{ => layouts}/input-512x512.png | Bin .../resources/layouts/lexical-logo-layout.xml | 272 ++++++++++++++++++ .../resources/{ => layouts}/output-24x24.png | Bin .../{ => layouts}/output-512x512.png | Bin 9 files changed, 597 insertions(+), 51 deletions(-) rename src/main/resources/{ => layouts}/display-24x24.png (100%) rename src/main/resources/{ => layouts}/display-512x512.png (100%) create mode 100644 src/main/resources/layouts/dynamic-logo-layout.xml rename src/main/resources/{ => layouts}/input-24x24.png (100%) rename src/main/resources/{ => layouts}/input-512x512.png (100%) create mode 100644 src/main/resources/layouts/lexical-logo-layout.xml rename src/main/resources/{ => layouts}/output-24x24.png (100%) rename src/main/resources/{ => layouts}/output-512x512.png (100%) diff --git a/src/main/java/org/tros/torgo/ControllerBase.java b/src/main/java/org/tros/torgo/ControllerBase.java index 644b65d..b455a9b 100644 --- a/src/main/java/org/tros/torgo/ControllerBase.java +++ b/src/main/java/org/tros/torgo/ControllerBase.java @@ -24,6 +24,7 @@ import bibliothek.gui.dock.common.SingleCDockable; import bibliothek.gui.dock.common.SingleCDockableFactory; import bibliothek.util.xml.XElement; +import bibliothek.util.xml.XIO; import org.tros.torgo.interpreter.CodeBlock; import org.tros.torgo.interpreter.InterpreterListener; import org.tros.torgo.interpreter.InterpreterThread; @@ -37,6 +38,8 @@ import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.StringWriter; @@ -67,6 +70,7 @@ import org.tros.torgo.swing.TorgoMenuBar; import org.tros.utils.swing.NamedWindow; import org.tros.utils.AutoResetEvent; +import org.tros.utils.PathUtils; /** * The main application. Controls GUI and interpreting process. @@ -82,6 +86,7 @@ public abstract class ControllerBase implements Controller { private String filename; protected final AutoResetEvent step; protected final AtomicBoolean isStepping; + private CControl dockControl; private final ArrayList viz = new ArrayList<>(); @@ -165,7 +170,7 @@ protected ControllerBase() { */ protected abstract InterpreterThread createInterpreterThread(String source); - public class TorgoSingleDockable extends DefaultSingleCDockable { + public static class TorgoSingleDockable extends DefaultSingleCDockable { public TorgoSingleDockable(String title, final Component panel) { super(title); @@ -174,7 +179,7 @@ public TorgoSingleDockable(String title, final Component panel) { } } - public class TorgoDockable extends DefaultDockable { + public static class TorgoDockable extends DefaultDockable { public TorgoDockable(String title, final Component panel) { super(title); @@ -184,7 +189,7 @@ public TorgoDockable(String title, final Component panel) { } /* This method simulates the creation of a layout */ - private XElement createLayout(Component display, ArrayList> input) { + private static XElement createLayout(Component display, ArrayList> input) { /* This method simulates the creation of a layout */ CControl control = new CControl(); control.getContentArea(); @@ -230,46 +235,13 @@ private void initSwing() { contentPane.add(tb, BorderLayout.NORTH); } -// SplitDockStation station = new SplitDockStation(); -// DockFrontend frontend = new DockFrontend(window); -// frontend.addRoot("station", station); -// window.add(station); -// -// /* The Perspective object is needed to convert the layout to the perspective-format. */ -// DockFrontendPerspective perspective = frontend.getPerspective(false); -// /* And trough the Perspective object we can directly access the root stations. */ -// SplitDockPerspective stationPerspective = (SplitDockPerspective) perspective.getRoot("station"); -// -// /* We are now creating the representation of the Dockables we are later going to add */ -// PerspectiveDockable dockableRed = torgoCanvas != null ? new FrontendDockablePerspective("Display") : null; -// PerspectiveDockable dockableGreen = new FrontendDockablePerspective("Input"); -// PerspectiveDockable dockableBlue = new FrontendDockablePerspective("Output"); -// /* Then we put two dockables in the same stack. */ -// StackDockPerspective stack = new StackDockPerspective(new PerspectiveDockable[]{dockableGreen, dockableBlue}, dockableGreen); -// /* The SplitDockStation internally uses a tree to represents its layout, here we create such a tree */ -// SplitDockPerspective.Leaf childRed = new SplitDockPerspective.Leaf(dockableRed, null, null, -1); -//// SplitDockPerspective.Leaf childGreen = new SplitDockPerspective.Leaf( dockableGreen, null, null, -1 ); -//// SplitDockPerspective.Leaf childBlue = new SplitDockPerspective.Leaf( dockableBlue, null, null, -1 ); -// SplitDockPerspective.Leaf childStack = new SplitDockPerspective.Leaf(stack, null, null, -1); -// SplitDockPerspective.Node node = new SplitDockPerspective.Node(Orientation.HORIZONTAL, 0.4, childRed, childStack, null, null, -1); -// stationPerspective.getRoot().setChild(node); -// -// if (dockableRed != null) { -// frontend.addDockable("Display", new TorgoDockable("Display", torgoCanvas.getComponent())); -// } -// for(ImmutablePair pair : torgoPanel.getTorgoComponents()) { -// frontend.addDockable(pair.left, new TorgoDockable(pair.left, pair.right)); -// } -// /* Finally the perspective is applied to the DockFrontend */ -// perspective.apply(); - - CControl control = new CControl(window); - window.add(control.getContentArea(), BorderLayout.CENTER); + dockControl = new CControl(window); + window.add(dockControl.getContentArea(), BorderLayout.CENTER); final ArrayList presetFilter = new ArrayList<>(); if (torgoCanvas != null) { presetFilter.add("Display"); } - for(ImmutablePair pair : torgoPanel.getTorgoComponents()) { + for (ImmutablePair pair : torgoPanel.getTorgoComponents()) { presetFilter.add(pair.left); } bibliothek.util.Filter filter = new bibliothek.util.Filter() { @@ -278,7 +250,7 @@ public boolean includes(String item) { return presetFilter.contains(item); } }; - control.addSingleDockableFactory(filter, new SingleCDockableFactory() { + dockControl.addSingleDockableFactory(filter, new SingleCDockableFactory() { @Override public SingleCDockable createBackup(String id) { TorgoSingleDockable ret = null; @@ -291,15 +263,45 @@ public SingleCDockable createBackup(String id) { } } } - if(ret != null) { - //TODO: find good icons for this.... - ImageIcon icon = Main.getIcon(ret.getTitleText().toLowerCase() + "-24x24.png"); + if (ret != null) { + ImageIcon icon = Main.getIcon("layouts/" + ret.getTitleText().toLowerCase() + "-24x24.png"); ret.setTitleIcon(icon); } return ret; } }); - control.readXML(createLayout(torgoCanvas != null ? torgoCanvas.getComponent() : null, torgoPanel.getTorgoComponents())); + + // Try to load a saved layout. + // If no layout exists or it fails, load from CLASSPATH/resources. + // If that fails, dynamically generate something. + String layoutFileName = PathUtils.getApplicationConfigDirectory(TorgoInfo.INSTANCE) + java.io.File.separatorChar + getLang() + "-layout.xml"; + File layoutFile = new File(layoutFileName); + boolean loaded = false; + if (layoutFile.exists()) { + try { + XElement elem = XIO.readUTF(new FileInputStream(layoutFile)); + dockControl.readXML(elem); + loaded = true; + } catch (FileNotFoundException ex) { + Logger.getLogger(ControllerBase.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(ControllerBase.class.getName()).log(Level.SEVERE, null, ex); + } + } + if (!loaded) { + try { + java.util.Enumeration resources = ClassLoader.getSystemClassLoader().getResources("layouts/" + this.getLang() + "-layout.xml"); + XElement elem = XIO.readUTF(resources.nextElement().openStream()); + dockControl.readXML(elem); + loaded = true; + } catch (IOException | java.util.NoSuchElementException ex) { + Logger.getLogger(ControllerBase.class.getName()).log(Level.WARNING, "Layout Error: Auto-generating: {0}", ex.getMessage()); + } + } + if (!loaded) { + XElement elem = createLayout(torgoCanvas != null ? torgoCanvas.getComponent() : null, torgoPanel.getTorgoComponents()); + dockControl.readXML(elem); + } JMenuBar mb = createMenuBar(); if (mb == null) { @@ -401,13 +403,19 @@ public void windowOpened(WindowEvent e) { /** * We only care if the window is closing so we can kill the - * interpreter thread. + * interpreter thread and save the layout. * * @param e */ @Override public void windowClosing(WindowEvent e) { stopInterpreter(); + try { + String layoutFile = PathUtils.getApplicationConfigDirectory(TorgoInfo.INSTANCE) + java.io.File.separatorChar + getLang() + "-layout.xml"; + dockControl.writeXML(new java.io.File(layoutFile)); + } catch (IOException ex) { + Logger.getLogger(ControllerBase.class.getName()).log(Level.SEVERE, null, ex); + } } @Override @@ -627,9 +635,6 @@ public void startInterpreter() { TorgoToolkit.getVisualization(item.getText()).create().watch(this.getLang(), this, interp); } } -// viz.stream().filter((item) -> (item.getState())).map((item) -> TorgoToolkit.getVisualization(item.getText()).create()).forEach((visualization) -> { -// visualization.watch(this.getLang(), this, interp); -// }); for (InterpreterListener l : listeners.getListeners()) { interp.addInterpreterListener(l); @@ -678,9 +683,6 @@ public void debugInterpreter() { TorgoToolkit.getVisualization(item.getText()).create().watch(this.getLang(), this, interp); } } -// viz.stream().filter((item) -> (item.getState())).map((item) -> TorgoToolkit.getVisualization(item.getText()).create()).forEach((visualization) -> { -// visualization.watch(this.getLang(), this, interp); -// }); for (InterpreterListener l : listeners.getListeners()) { interp.addInterpreterListener(l); diff --git a/src/main/resources/display-24x24.png b/src/main/resources/layouts/display-24x24.png similarity index 100% rename from src/main/resources/display-24x24.png rename to src/main/resources/layouts/display-24x24.png diff --git a/src/main/resources/display-512x512.png b/src/main/resources/layouts/display-512x512.png similarity index 100% rename from src/main/resources/display-512x512.png rename to src/main/resources/layouts/display-512x512.png diff --git a/src/main/resources/layouts/dynamic-logo-layout.xml b/src/main/resources/layouts/dynamic-logo-layout.xml new file mode 100644 index 0000000..80d52fb --- /dev/null +++ b/src/main/resources/layouts/dynamic-logo-layout.xml @@ -0,0 +1,272 @@ + + + + + + smooth + + + + + + + + + + + true + + + 0 + dock.PlaceholderList + + + + + + + dock.CExternalizeArea + + + + + + + + + true + + + + 0 + dock.PlaceholderList + + + + + + + dock.CContentArea.minimize + + + + + + + + + true + + + + 0 + dock.PlaceholderList + + + + + + + dock.CContentArea.minimize + + + + + + + + + true + + + + 0 + dock.PlaceholderList + + + + + + + dock.CContentArea.minimize + + + + + + + + + ccontrol center + true + + false + + + + dock.single.Display + + + + + + dock.single.Input + + + + + dock.single.Output + + + + + + + + + + dock.CContentArea.center + + + + + + + + Output + + + + + + + + + + Input + + + + + + + + + + Display + + + + + + + + + + + + true + + + + 0 + dock.PlaceholderList + + + + + + + dock.CContentArea.minimize + + + + + + + + + + + + dock.mode.normal + + + + dock.mode.normal + ccontrol center + + + dock.single.Output + + + + + + + + + + + + dock.mode.normal + + + + dock.mode.normal + ccontrol center + + + dock.single.Input + + + + + + + + + + + + dock.mode.normal + + + + dock.mode.normal + ccontrol center + + + dock.single.Display + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/input-24x24.png b/src/main/resources/layouts/input-24x24.png similarity index 100% rename from src/main/resources/input-24x24.png rename to src/main/resources/layouts/input-24x24.png diff --git a/src/main/resources/input-512x512.png b/src/main/resources/layouts/input-512x512.png similarity index 100% rename from src/main/resources/input-512x512.png rename to src/main/resources/layouts/input-512x512.png diff --git a/src/main/resources/layouts/lexical-logo-layout.xml b/src/main/resources/layouts/lexical-logo-layout.xml new file mode 100644 index 0000000..80d52fb --- /dev/null +++ b/src/main/resources/layouts/lexical-logo-layout.xml @@ -0,0 +1,272 @@ + + + + + + smooth + + + + + + + + + + + true + + + 0 + dock.PlaceholderList + + + + + + + dock.CExternalizeArea + + + + + + + + + true + + + + 0 + dock.PlaceholderList + + + + + + + dock.CContentArea.minimize + + + + + + + + + true + + + + 0 + dock.PlaceholderList + + + + + + + dock.CContentArea.minimize + + + + + + + + + true + + + + 0 + dock.PlaceholderList + + + + + + + dock.CContentArea.minimize + + + + + + + + + ccontrol center + true + + false + + + + dock.single.Display + + + + + + dock.single.Input + + + + + dock.single.Output + + + + + + + + + + dock.CContentArea.center + + + + + + + + Output + + + + + + + + + + Input + + + + + + + + + + Display + + + + + + + + + + + + true + + + + 0 + dock.PlaceholderList + + + + + + + dock.CContentArea.minimize + + + + + + + + + + + + dock.mode.normal + + + + dock.mode.normal + ccontrol center + + + dock.single.Output + + + + + + + + + + + + dock.mode.normal + + + + dock.mode.normal + ccontrol center + + + dock.single.Input + + + + + + + + + + + + dock.mode.normal + + + + dock.mode.normal + ccontrol center + + + dock.single.Display + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/output-24x24.png b/src/main/resources/layouts/output-24x24.png similarity index 100% rename from src/main/resources/output-24x24.png rename to src/main/resources/layouts/output-24x24.png diff --git a/src/main/resources/output-512x512.png b/src/main/resources/layouts/output-512x512.png similarity index 100% rename from src/main/resources/output-512x512.png rename to src/main/resources/layouts/output-512x512.png