summaryrefslogtreecommitdiffstats
path: root/logo/src/xlogo/gui
diff options
context:
space:
mode:
Diffstat (limited to 'logo/src/xlogo/gui')
-rw-r--r--logo/src/xlogo/gui/AImprimer.java90
-rw-r--r--logo/src/xlogo/gui/Editor.java396
-rw-r--r--logo/src/xlogo/gui/EditorTextArea.java58
-rw-r--r--logo/src/xlogo/gui/EditorTextPane.java83
-rw-r--r--logo/src/xlogo/gui/EditorTextZone.java303
-rw-r--r--logo/src/xlogo/gui/HistoryPanel.java416
-rw-r--r--logo/src/xlogo/gui/Lis.java78
-rw-r--r--logo/src/xlogo/gui/MyTextAreaDialog.java59
-rw-r--r--logo/src/xlogo/gui/MyToolBar.java126
-rw-r--r--logo/src/xlogo/gui/ReplaceFrame.java265
-rw-r--r--logo/src/xlogo/gui/SearchFrame.java189
-rw-r--r--logo/src/xlogo/gui/Searchable.java36
-rw-r--r--logo/src/xlogo/gui/Traduc.java216
-rw-r--r--logo/src/xlogo/gui/ZoneCommande.java271
-rw-r--r--logo/src/xlogo/gui/ZoneEdition.java196
-rw-r--r--logo/src/xlogo/gui/components/ColorStyleSelectionPanel.java232
-rw-r--r--logo/src/xlogo/gui/components/ProcedureSearch.java309
-rw-r--r--logo/src/xlogo/gui/components/TurtleComboBox.java169
-rw-r--r--logo/src/xlogo/gui/components/X4SComponent.java81
-rw-r--r--logo/src/xlogo/gui/components/X4SFrame.java40
-rw-r--r--logo/src/xlogo/gui/components/X4SGui.java112
-rw-r--r--logo/src/xlogo/gui/components/fileslist/11_alerts_and_states_error.pngbin0 -> 1285 bytes
-rw-r--r--logo/src/xlogo/gui/components/fileslist/1_navigation_accept.pngbin0 -> 1197 bytes
-rw-r--r--logo/src/xlogo/gui/components/fileslist/5_content_discard.pngbin0 -> 1359 bytes
-rw-r--r--logo/src/xlogo/gui/components/fileslist/5_content_edit.pngbin0 -> 1506 bytes
-rw-r--r--logo/src/xlogo/gui/components/fileslist/5_content_remove.pngbin0 -> 1202 bytes
-rw-r--r--logo/src/xlogo/gui/components/fileslist/FilesList.java665
-rw-r--r--logo/src/xlogo/gui/components/fileslist/FilesListItem.java542
-rw-r--r--logo/src/xlogo/gui/components/fileslist/IFilesListItem.java60
-rw-r--r--logo/src/xlogo/gui/components/fileslist/close_icon2.pngbin0 -> 22621 bytes
-rw-r--r--logo/src/xlogo/gui/components/fileslist/new_content.pngbin0 -> 1099 bytes
-rw-r--r--logo/src/xlogo/gui/preferences/AbstractPanelColor.java143
-rw-r--r--logo/src/xlogo/gui/preferences/PanelColor.java45
-rw-r--r--logo/src/xlogo/gui/translation/BottomPanel.java89
-rw-r--r--logo/src/xlogo/gui/translation/FirstPanel.java237
-rw-r--r--logo/src/xlogo/gui/translation/MyTable.java375
-rw-r--r--logo/src/xlogo/gui/translation/TopPanel.java63
-rw-r--r--logo/src/xlogo/gui/translation/TranslateXLogo.java178
-rw-r--r--logo/src/xlogo/gui/welcome/WelcomeScreen.java518
-rw-r--r--logo/src/xlogo/gui/welcome/WorkspaceSettings.java183
-rw-r--r--logo/src/xlogo/gui/welcome/settings/tabs/AbstractWorkspacePanel.java269
-rw-r--r--logo/src/xlogo/gui/welcome/settings/tabs/ContestTab.java197
-rw-r--r--logo/src/xlogo/gui/welcome/settings/tabs/GlobalTab.java230
-rw-r--r--logo/src/xlogo/gui/welcome/settings/tabs/SyntaxHighlightingTab.java288
-rw-r--r--logo/src/xlogo/gui/welcome/settings/tabs/WorkspaceCreationPanel.java144
-rw-r--r--logo/src/xlogo/gui/welcome/settings/tabs/WorkspaceTab.java537
46 files changed, 8488 insertions, 0 deletions
diff --git a/logo/src/xlogo/gui/AImprimer.java b/logo/src/xlogo/gui/AImprimer.java
new file mode 100644
index 0000000..7f20ecb
--- /dev/null
+++ b/logo/src/xlogo/gui/AImprimer.java
@@ -0,0 +1,90 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+/**
+ * Title : XLogo
+ * Description : XLogo is an interpreter for the Logo
+ * programming language
+ * @author Loïc Le Coq
+ */
+package xlogo.gui;
+
+import java.awt.print.*;
+import javax.swing.*;
+
+import java.awt.Image;
+import java.awt.Graphics;
+
+public class AImprimer extends JPanel implements Printable, Runnable {
+ private static final long serialVersionUID = 1L;
+ private Image image;
+
+ public AImprimer(Image image) {
+ this.image = image;
+ }
+
+ public void run() {
+ Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
+ PrinterJob job = PrinterJob.getPrinterJob();
+ job.setPrintable(this);
+ if (job.printDialog()) {
+ try {
+ job.print();
+ } catch (PrinterException ex) {
+ System.out.println(ex.getMessage());
+ }
+ }
+ }
+
+ public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
+ double largeur = image.getWidth(this);
+ double hauteur = image.getHeight(this);
+ double facteur = pf.getImageableWidth() / largeur; // largeur
+ // imprimable sur la
+ // feuille
+ double facteur2 = pf.getImageableHeight() / hauteur; // hauteur
+ // imprimable
+ // sur la
+ // feuille
+
+ if (facteur < 1 | facteur2 < 1) {
+ facteur = Math.min(facteur, facteur2);
+ image = image.getScaledInstance((int) (largeur * facteur),
+ (int) (hauteur * facteur), Image.SCALE_SMOOTH);
+ }
+ largeur = image.getWidth(this); // permet d'attendre que l'image soit
+ // bien créée
+ hauteur = image.getHeight(this);
+ if (pi < 1) {
+ g.drawImage(this.image, (int) pf.getImageableX(), (int) pf
+ .getImageableY(), this);
+ return (Printable.PAGE_EXISTS);
+ } else
+ return Printable.NO_SUCH_PAGE;
+ }
+} \ No newline at end of file
diff --git a/logo/src/xlogo/gui/Editor.java b/logo/src/xlogo/gui/Editor.java
new file mode 100644
index 0000000..6da4cd8
--- /dev/null
+++ b/logo/src/xlogo/gui/Editor.java
@@ -0,0 +1,396 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyListener;
+
+import javax.swing.GroupLayout;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import xlogo.storage.WSManager;
+import xlogo.storage.user.UserConfig;
+import xlogo.storage.workspace.WorkspaceConfig;
+import xlogo.utils.Utils;
+import xlogo.Application;
+import xlogo.kernel.userspace.UserSpace;
+import xlogo.messages.MessageKeys;
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.Logo;
+
+/**
+ * Title : XLogo Description : XLogo is an interpreter for the Logo programming
+ * language
+ * <p>
+ * <p>
+ * Changes made in July 2013 by Marko Zivkovic: All the procedure analyzing is
+ * moved to class 'Workspace' which was then renamed to {@link UserSpace}.
+ * Reason: This is a GUI component and it should not do much model manipulation
+ * things. As often in XLogo this was an issue of weak separation of concerns,
+ * leading to bad modifiability, extensibility, changeability, and
+ * maintainability. Better have the Workspace deal with all the workspace
+ * management. For the editor, it's enough to edit text, do syntax highlighting,
+ * and provide the input text to some other specialized class.
+ *
+ * @author Loïc Le Coq, Marko Zivkovic
+ *
+ */
+
+/*
+ * The main class for the Editor windows
+ */
+public class Editor implements ActionListener
+{
+ private JPanel mainPanel = new JPanel();
+ private JPanel menu = new JPanel();
+ private JButton chercher, undo, redo;
+ private JScrollPane scroll;
+ private EditorTextZone textZone;
+ // private ZoneEdition zonedition;
+
+ private Application app;
+ private ReplaceFrame sf;
+ UserConfig uc;
+
+ private KeyListener logoTextAnalyzerTrigger;
+ //private ArrayList<ProcedureErrorMessage> errors = new ArrayList<ProcedureErrorMessage>();
+
+
+ public Editor(Application app)
+ {
+ super();
+ mainPanel.setOpaque(true);
+ this.app = app;
+ uc = WSManager.getUserConfig();
+
+ try
+ {
+ initGui();
+ }
+ catch (Exception e)
+ {
+ DialogMessenger.getInstance().dispatchError(
+ Logo.messages.getString(MessageKeys.GENERAL_ERROR_TITLE),
+ Logo.messages.getString(MessageKeys.ERROR_WHILE_CREATING_EDITOR));
+ }
+
+ }
+
+ public String getText()
+ {
+ return textZone.getText();
+ }
+
+ public JComponent getComponent()
+ {
+ return mainPanel;
+ }
+
+ /**
+ * Set the text of this component and displays it. <br>
+ * If the Editor was already open, it will store the old file and then
+ * display the new file.
+ *
+ * @param file
+ */
+ public void setText(String text)
+ {
+ textZone.clearText();
+ setEditorStyledText(text);
+ textZone.requestFocus();
+ }
+
+ /**
+ * @author Marko Zivkovic
+ */
+ public void displayProcedure(String procedureName)
+ {
+ String to = Logo.messages.getString("pour");
+ if (!textZone.find(to + " " + procedureName, false))
+ textZone.find(to + " " + procedureName, true);
+
+ }
+
+ private void initGui() throws Exception
+ {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+
+ // Init All other components
+ scroll = new JScrollPane();
+ if (wc.isSyntaxHighlightingEnabled())
+ {
+ textZone = new EditorTextPane(this);
+ textZone.getTextComponent().addKeyListener(logoTextAnalyzerTrigger);
+ }
+ else
+ textZone = new EditorTextArea(this);
+
+ sf = new ReplaceFrame(app.getFrame(), textZone);
+
+ scroll.setPreferredSize(new Dimension(500, 500));
+ scroll.getViewport().add(textZone.getTextComponent(), null);
+ sf = new ReplaceFrame(app.getFrame(), textZone);
+
+ applyLayout();
+ initToolbar();
+ }
+
+ private void applyLayout()
+ {
+ GroupLayout groupLayout = new GroupLayout(mainPanel);
+ mainPanel.setLayout(groupLayout);
+
+ groupLayout.setAutoCreateContainerGaps(true);
+ groupLayout.setAutoCreateGaps(true);
+
+ groupLayout.setVerticalGroup(
+ groupLayout.createSequentialGroup()
+ .addComponent(menu)
+ .addComponent(scroll));
+
+ groupLayout.setHorizontalGroup(
+ groupLayout.createParallelGroup()
+ .addComponent(menu)
+ .addComponent(scroll));
+
+ FlowLayout flowLayout = new FlowLayout();
+ menu.setLayout(flowLayout);
+ mainPanel.add(menu);
+ mainPanel.add(scroll);
+ }
+
+ /*
+ * Below everything is inherited from XLogo, except for minor changes due to refactoring
+ */
+
+
+ private void initToolbar()
+ {
+ menu.setMaximumSize(new Dimension(Integer.MAX_VALUE, 40));
+
+ chercher = getIconButton("chercher.png","find");
+ undo = getIconButton("undo.png","editor.undo");
+ redo = getIconButton("redo.png","editor.redo");
+
+ undo.setEnabled(false);
+ redo.setEnabled(false);
+
+ menu.add(chercher);
+ menu.add(undo);
+ menu.add(redo);
+
+ }
+
+ private JButton getIconButton(String iconName, String description)
+ {
+ JButton btn = new JButton();
+ if (iconName != null)
+ btn.setIcon(Utils.dimensionne_image(iconName, mainPanel));
+
+ btn.setToolTipText(Logo.messages.getString(description));
+ btn.setActionCommand(Logo.messages.getString(description));
+ btn.addActionListener(this);
+ return btn;
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ String cmd = e.getActionCommand();
+ if (cmd.equals(Logo.messages.getString("find")))
+ {
+ if (!sf.isVisible())
+ {
+ sf.setSize(350, 350);
+ sf.setVisible(true);
+ }
+ }
+ // Undo Action
+ else if (cmd.equals(Logo.messages.getString("editor.undo")))
+ {
+ textZone.getUndoManager().undo();
+ updateUndoRedoButtons();
+ }
+ // Redo Action
+ else if (cmd.equals(Logo.messages.getString("editor.redo")))
+ {
+ textZone.getUndoManager().redo();
+ updateUndoRedoButtons();
+ }
+ }
+
+ // Change Syntax Highlighting for the editor
+ public void initStyles(int c_comment, int sty_comment, int c_primitive, int sty_primitive, int c_parenthese,
+ int sty_parenthese, int c_operande, int sty_operande)
+ {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+
+ if (textZone.supportHighlighting())
+ {
+ ((EditorTextPane) textZone).getDsd().initStyles(wc.getCommentColor(), wc.getCommentStyle(),
+ wc.getPrimitiveColor(), wc.getPrimitiveStyle(), wc.getBraceColor(),
+ wc.getBraceStyle(), wc.getOperatorColor(), wc.getOperatorStyle());
+ }
+ }
+
+ // Enable or disable Syntax Highlighting
+ /*
+ * public void setColoration(boolean b){ if (textZone.supportHighlighting())
+ * ((EditorTextPane)textZone).getDsd().setColoration(b); }
+ */
+ public void setEditorFont(Font f)
+ {
+ textZone.setFont(f);
+ }
+
+ /**
+ * Erase all text
+ */
+ public void clearText()
+ {
+ textZone.clearText();
+ }
+
+ /**
+ * Convert the textZone from a JTextArea to a JTextPane To allow Syntax
+ * Highlighting
+ */
+ public void toTextPane()
+ {
+ textZone.getTextComponent().removeKeyListener(logoTextAnalyzerTrigger);
+ scroll.getViewport().removeAll();// .remove(textZone.getTextComponent());
+ String s = textZone.getText();
+ textZone = new EditorTextPane(this);
+ sf = new ReplaceFrame(app.getFrame(), textZone);
+ textZone.ecris(s);
+ textZone.getTextComponent().addKeyListener(logoTextAnalyzerTrigger);
+ scroll.getViewport().add(textZone.getTextComponent());
+ scroll.revalidate();
+ }
+
+ /**
+ * Convert the textZone from a JTextPane to a JTextArea Cause could be that:
+ * - Syntax Highlighting is disabled - Large text to display in the editor
+ */
+ public void toTextArea()
+ {
+ /*
+ * Marko : for large text or disabled highlighting, we also don't want error messages to be produced while typing.
+ *
+ */
+ textZone.getTextComponent().removeKeyListener(logoTextAnalyzerTrigger);
+ String s = textZone.getText();
+ scroll.getViewport().removeAll();// .remove(textZone.getTextComponent());
+ textZone = new EditorTextArea(this);
+ sf = new ReplaceFrame(app.getFrame(), textZone);
+ textZone.ecris(s);
+ scroll.getViewport().add(textZone.getTextComponent());
+ scroll.revalidate();
+ }
+
+ /**
+ * Inserts the text at the current caret position.
+ *
+ * @param txt
+ */
+ public void setEditorStyledText(String txt)
+ {
+ if (txt.length() < 100000)
+ {
+ textZone.ecris(txt);
+ }
+ else
+ {
+ if (textZone instanceof EditorTextPane)
+ {
+ WSManager.getWorkspaceConfig().setSyntaxHighlightingEnabled(false);
+ toTextArea();
+ textZone.ecris(txt);
+ }
+ else
+ textZone.ecris(txt);
+ }
+ }
+
+ /**
+ * append a procedure to the end of the document.
+ *
+ * @param program
+ * @author Marko Zivkovic
+ */
+ public void append(String procedure)
+ {
+ if (procedure.length() < 100000)
+ {
+ textZone.append(procedure);
+ }
+ else
+ {
+ if (textZone instanceof EditorTextPane)
+ {
+ WSManager.getWorkspaceConfig().setSyntaxHighlightingEnabled(false);
+ toTextArea();
+ textZone.append(procedure);
+ }
+ else
+ textZone.append(procedure);
+ }
+ }
+
+ public void focus_textZone()
+ {
+ textZone.requestFocus();
+ }
+
+ public void discardAllEdits()
+ {
+ textZone.getUndoManager().discardAllEdits();
+ updateUndoRedoButtons();
+ }
+
+ protected void updateUndoRedoButtons()
+ {
+ if (textZone.getUndoManager().canRedo())
+ redo.setEnabled(true);
+ else
+ redo.setEnabled(false);
+ if (textZone.getUndoManager().canUndo())
+ undo.setEnabled(true);
+ else
+ undo.setEnabled(false);
+ }
+
+
+}
diff --git a/logo/src/xlogo/gui/EditorTextArea.java b/logo/src/xlogo/gui/EditorTextArea.java
new file mode 100644
index 0000000..387b30f
--- /dev/null
+++ b/logo/src/xlogo/gui/EditorTextArea.java
@@ -0,0 +1,58 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import javax.swing.JTextArea;
+
+public class EditorTextArea extends EditorTextZone {
+ EditorTextArea(Editor editor){
+ super(editor);
+ jtc=new JTextArea();
+ initGui();
+ }
+ public void setActive(boolean b){}
+
+ protected void ecris(String s){
+ int deb=jtc.getCaretPosition();
+ ((JTextArea)jtc).insert(s,deb);
+ jtc.setCaretPosition(deb+s.length());
+ }
+
+ /**
+ * Added 21.6.2013
+ * <p> this method is used to append a program to the end of the editor.
+ * It is used for the Logo command "define".
+ * @author Marko Zivkovic
+ */
+ @Override
+ protected void append(String program) {
+ int deb= jtc.getText().length();
+ ((JTextArea)jtc).insert(program,deb);
+ }
+}
diff --git a/logo/src/xlogo/gui/EditorTextPane.java b/logo/src/xlogo/gui/EditorTextPane.java
new file mode 100644
index 0000000..fd069fe
--- /dev/null
+++ b/logo/src/xlogo/gui/EditorTextPane.java
@@ -0,0 +1,83 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import javax.swing.text.BadLocationException;
+import xlogo.StyledDocument.DocumentLogo;
+
+
+public class EditorTextPane extends EditorTextZone{
+ private DocumentLogo dsd;
+ EditorTextPane(Editor editor){
+ super(editor);
+ dsd=new DocumentLogo();
+ jtc=new ZoneEdition(this);
+ initGui();
+ initHighlight();
+ }
+ protected void initHighlight(){
+ jtc.setDocument(dsd);
+ dsd.addUndoableEditListener(new MyUndoableEditListener());
+ }
+ protected DocumentLogo getDsd(){
+ return dsd;
+ }
+ protected void ecris(String mot){
+ try{
+ int deb=jtc.getCaretPosition();
+ dsd.insertString(deb,mot,null);
+ jtc.setCaretPosition(deb+mot.length());
+ }
+ catch(BadLocationException e){}
+ }
+ /**
+ * Added 21.6.2013
+ * <p> this method is used to append a program to the end of the editor.
+ * It is used for the Logo command "define".
+ * @author Marko Zivkovic
+ */
+ @Override
+ protected void append(String program) {
+ try{
+ int deb= dsd.getLength();
+ dsd.insertString(deb,program,null);
+ }
+ catch(BadLocationException e){}
+
+ }
+
+ public void setActive(boolean b){
+ ((ZoneEdition)jtc).setActive(b);
+ }
+
+ protected boolean supportHighlighting(){
+ return true;
+ }
+
+}
diff --git a/logo/src/xlogo/gui/EditorTextZone.java b/logo/src/xlogo/gui/EditorTextZone.java
new file mode 100644
index 0000000..b14749b
--- /dev/null
+++ b/logo/src/xlogo/gui/EditorTextZone.java
@@ -0,0 +1,303 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.util.Stack;
+import java.util.StringTokenizer;
+import javax.swing.event.UndoableEditEvent;
+import javax.swing.event.UndoableEditListener;
+import javax.swing.text.AbstractDocument;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultHighlighter;
+import javax.swing.undo.UndoManager;
+import javax.swing.undo.UndoableEdit;
+import xlogo.Popup;
+/**
+ *
+ * @author loic
+ * This class is the generic component to display the text in the editor
+ * If there are too many characters, it is a JTextArea <br>
+ * Else it's a JtextPane that allows Syntax Highlighting
+ */
+public abstract class EditorTextZone implements Searchable, Printable {
+ private Editor editor;
+ private StringBuffer text;
+ protected JTextComponent jtc;
+ private Popup jpop;
+
+ private boolean highlightWasSet = false;
+
+ // When printing the text area, this stack stores each page
+ private Stack<String> pages=null;
+ // To remember undoable edits
+ private UndoManager undoManager;
+ private int startOffset,endOffset;
+ /**
+ * Default constructor for this generic constructor
+ *
+ * @param editor The parent editor
+ */
+ EditorTextZone(Editor editor){
+ this.editor=editor;
+
+ }
+ protected void initGui(){
+ // Adds the JPopup Menu
+ jpop=new Popup(editor,jtc);
+ MouseListener popupListener = new PopupListener();
+ jtc.addMouseListener(popupListener);
+
+ jtc.addMouseListener(new MouseListener(){
+
+ @Override
+ public void mouseReleased(MouseEvent e) { }
+
+ @Override
+ public void mousePressed(MouseEvent e)
+ {
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) { }
+
+ @Override
+ public void mouseEntered(MouseEvent e) { }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (highlightWasSet)
+ {
+ removeHighlight();
+ highlightWasSet = false;
+ }
+ }
+ });
+ undoManager=new UndoManager();
+ }
+ /**
+ * Erase all text
+ */
+ protected void clearText(){
+ jtc.setText("");
+ }
+
+ public boolean find(String searchText,boolean forward){
+ try
+ {
+ int index;
+ String element = searchText.toLowerCase();
+ text = new StringBuffer(jtc.getText().toLowerCase());
+ // Find forward
+ if (forward)
+ index = text.indexOf(element, jtc.getCaretPosition());
+ else
+ index = text.lastIndexOf(element, jtc.getCaretPosition());
+ if (index == -1)
+ {
+ startOffset = 0;
+ endOffset = 0;
+ return false;
+ }
+ else
+ {
+ jtc.getHighlighter().removeAllHighlights();
+ startOffset = index;
+ endOffset = index + element.length();
+ jtc.getHighlighter().addHighlight(startOffset, endOffset, DefaultHighlighter.DefaultPainter);
+ if (forward)
+ jtc.setCaretPosition(index + element.length());
+ else if (index > 1)
+ jtc.setCaretPosition(index - 1);
+
+ highlightWasSet = true;
+ return true;
+ }
+ }
+ catch(NullPointerException e){} // If the combo is empty
+ catch(BadLocationException e){}
+ return false;
+ }
+ public void replace(String element, boolean forward){
+ text.delete(startOffset, endOffset);
+ try{
+ text.insert(startOffset,element );
+
+ }
+ catch(NullPointerException err){}
+ jtc.setText(text.toString());
+ if (forward) jtc.setCaretPosition(endOffset);
+ else if (startOffset>1) jtc.setCaretPosition(startOffset-1);
+
+ }
+ public void replaceAll(String element, String substitute){
+
+ try {
+ String string=jtc.getText().toString();
+ string=string.replaceAll(element, substitute);
+ jtc.setText(string);
+ }
+ catch(NullPointerException e2){}
+
+ }
+ public void removeHighlight(){
+ jtc.getHighlighter().removeAllHighlights();
+ }
+
+ class MyUndoableEditListener implements UndoableEditListener{
+ public void undoableEditHappened(UndoableEditEvent e){
+ UndoableEdit edit = e.getEdit();
+ // Include this method to ignore syntax changes
+ if (edit instanceof AbstractDocument.DefaultDocumentEvent &&
+ ((AbstractDocument.DefaultDocumentEvent)edit).getType() ==
+ AbstractDocument.DefaultDocumentEvent.EventType.CHANGE) {
+ return;
+ }
+ // Remember the edit
+ undoManager.addEdit(edit);
+// System.out.println(e.getEdit().getPresentationName());
+ editor.updateUndoRedoButtons();
+ }
+}
+ protected UndoManager getUndoManager(){
+ return undoManager;
+ }
+ protected String getText(){
+ return jtc.getText();
+ }
+ public void requestFocus(){
+ jtc.requestFocus();
+ }
+ protected JTextComponent getTextComponent(){
+ return jtc;
+ }
+ protected boolean supportHighlighting(){
+ return false;
+ }
+
+ protected void setFont(Font f){
+ jtc.setFont(f);
+ }
+ protected Font getFont(){
+ return jtc.getFont();
+ }
+ // To print the text Area
+
+ public int print(Graphics g,PageFormat pf, int pi) throws PrinterException{
+ if(pi<pages.size()){
+ jtc.setText(pages.get(pi));
+ g.translate((int)pf.getImageableX(),(int)pf.getImageableY());
+ jtc.paint(g);
+ return(Printable.PAGE_EXISTS);
+ }
+ else return Printable.NO_SUCH_PAGE;
+ }
+ protected void actionPrint(){
+ Font font=jtc.getFont();
+ String txt=jtc.getText();
+ jtc.setFont(new Font(font.getFontName(),Font.PLAIN,10));
+ jtc.setText(txt);
+ PrinterJob job = PrinterJob.getPrinterJob();
+ job.setPrintable(this,job.defaultPage());
+ double h_imp=job.defaultPage().getImageableHeight();
+ java.awt.FontMetrics fm = jtc.getFontMetrics(jtc.getFont());
+ pages=new Stack<String>();
+ StringTokenizer st = new StringTokenizer(txt, "\n");
+ String page="";
+ // System.out.println("hauteur "+fm.getHeight()+" "+h_imp);
+ int compteur=0;
+ while (st.hasMoreTokens()) {
+ String element = st.nextToken();
+ compteur+=fm.getHeight();
+ if (compteur>h_imp) {
+ pages.push(page);
+ page = element;
+ compteur=fm.getHeight();
+ }
+ else page+= element+"\n";
+ }
+ if (!page.equals("")) pages.push(page);
+ if (job.printDialog()) {
+ try {
+ job.print();
+ }
+ catch (PrinterException ex) {
+ System.out.println(ex.getMessage());
+ }
+ }
+ font=jtc.getFont();
+ jtc.setFont(new Font(font.getFontName(),Font.PLAIN,12));
+ jtc.setText(txt);
+ }
+ // Edit Actions
+ protected void copy(){
+ jtc.copy();
+ }
+ protected void cut(){
+ jtc.cut();
+ }
+ protected void paste(){
+ jtc.paste();
+ }
+
+ // setText Method for Text Zone
+ protected void setText(String s){
+ jtc.setText(s);
+ }
+ protected abstract void ecris(String s);
+
+ protected abstract void append(String s);
+
+ abstract void setActive(boolean b);
+ class PopupListener extends MouseAdapter {
+
+ public void mousePressed(MouseEvent e) {
+ maybeShowPopup(e);
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ maybeShowPopup(e);
+ }
+
+ private void maybeShowPopup(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ jpop.show(e.getComponent(), e.getX(), e.getY());
+ }
+ }
+ }
+}
diff --git a/logo/src/xlogo/gui/HistoryPanel.java b/logo/src/xlogo/gui/HistoryPanel.java
new file mode 100644
index 0000000..d1c17ba
--- /dev/null
+++ b/logo/src/xlogo/gui/HistoryPanel.java
@@ -0,0 +1,416 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import javax.swing.*;
+
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
+import javax.swing.text.rtf.RTFEditorKit;
+import javax.swing.text.*;
+
+import java.io.*;
+
+import xlogo.storage.WSManager;
+import xlogo.storage.global.GlobalConfig;
+import xlogo.storage.user.UserConfig;
+import xlogo.storage.workspace.WorkspaceConfig;
+import xlogo.utils.Utils;
+import xlogo.utils.ExtensionFichier;
+import xlogo.StyledDocument.DocumentLogoHistorique;
+import xlogo.Application;
+import xlogo.kernel.DrawPanel;
+import xlogo.kernel.LogoError;
+import xlogo.messages.async.AsyncMediumAdapter;
+import xlogo.messages.async.AsyncMessage;
+import xlogo.messages.async.AsyncMessenger;
+import xlogo.messages.async.history.HistoryMessenger;
+import xlogo.messages.async.history.HistoryWriter;
+import xlogo.Logo;
+
+/**
+ * Title : XLogo
+ * Description : XLogo is an interpreter for the Logo
+ * programming language
+ *
+ * @author Loïc Le Coq
+ */
+public class HistoryPanel extends JPanel implements HistoryWriter
+{
+
+ private static final long serialVersionUID = 1L;
+ // numéro identifiant la police de
+ // l'historique avec "ecris"
+ public static int fontPrint = GlobalConfig.police_id(WSManager.getWorkspaceConfig().getFont()); // TODO
+ // how
+ // to
+ // remove
+ // fontPrint?
+ // Error@static?
+ private ImageIcon ianimation = Utils.dimensionne_image("animation.png", this);
+ private JLabel label_animation = new JLabel(ianimation);
+ private MouseAdapter mouseAdapt;
+ private Color couleur_texte = Color.BLUE;
+ private int taille_texte = 12;
+ private JPanel jPanel1 = new JPanel();
+ private JScrollPane jScrollPane1 = new JScrollPane();
+ private Historique historique = new Historique();
+ private DocumentLogoHistorique dsd;
+ private BorderLayout borderLayout1 = new BorderLayout();
+ private Application cadre;
+
+ public HistoryPanel()
+ {
+ }
+
+ public HistoryPanel(Application cadre) {
+ historique.setFont(WSManager.getWorkspaceConfig().getFont());
+ this.cadre=cadre;
+ try {
+ jbInit();
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+ dsd=new DocumentLogoHistorique();
+ historique.setDocument(dsd);
+
+ /*
+ * Added by Marko Zivkovic to decouple HistoryPanel from the rest of the old XLogo classes
+ */
+ HistoryMessenger.getInstance().setMedium(new AsyncMediumAdapter<AsyncMessage<HistoryWriter>, HistoryWriter>(){
+
+ public boolean isReady()
+ {
+ return getThis().historique.isDisplayable();
+ }
+
+ public HistoryWriter getMedium()
+ {
+ return getThis();
+ }
+
+ public void addMediumReadyListener(final AsyncMessenger messenger)
+ {
+ historique.addAncestorListener(new AncestorListener(){
+ public void ancestorRemoved(AncestorEvent event)
+ {
+ maybeMediumReadyEvent();
+ }
+ public void ancestorMoved(AncestorEvent event)
+ {
+ maybeMediumReadyEvent();
+ }
+ public void ancestorAdded(AncestorEvent event)
+ {
+ maybeMediumReadyEvent();
+ }
+
+ private void maybeMediumReadyEvent()
+ {
+ if (isDisplayable())
+ messenger.onMediumReady();
+ }
+
+ });
+ }
+ });
+ }
+
+ private HistoryPanel getThis()
+ {
+ return this;
+ }
+
+ public Color getCouleurtexte()
+ {
+ return couleur_texte;
+ }
+
+ public int police()
+ {
+ return taille_texte;
+ }
+
+ public void vide_texte()
+ {
+ historique.setText("");
+ }
+
+ /**
+ * Made private by Marko Zivkovic.
+ * This functionality is now publicly available through the implementation of {@link HistoryWriter#writeMessage(String, String)}
+ * @param sty
+ * @param texte
+ */
+ private void ecris(String sty, String texte)
+ {
+ try
+ {
+ int longueur = historique.getDocument().getLength();
+ if (texte.length() > 32000)
+ throw new LogoError( Logo.messages.getString("chaine_trop_longue"));
+ if (longueur + texte.length() < 65000)
+ {
+ try
+ {
+ dsd.setStyle(sty);
+ dsd.insertString(dsd.getLength(), texte, null);
+ historique.setCaretPosition(dsd.getLength());
+ }
+ catch (BadLocationException e)
+ {}
+ }
+ else
+ {
+ vide_texte();
+ }
+ }
+ catch (LogoError e2)
+ {}
+ }
+
+ private void jbInit() throws Exception
+ {
+
+ this.setLayout(borderLayout1);
+ this.setMinimumSize(new Dimension(4, 4));
+ this.setPreferredSize(new Dimension(600, 40));
+ historique.setForeground(Color.black);
+ historique.setEditable(false);
+ this.add(jPanel1, BorderLayout.EAST);
+ label_animation.setToolTipText(Logo.messages.getString("animation_active"));
+ this.add(jScrollPane1, BorderLayout.CENTER);
+ jScrollPane1.getViewport().add(historique, null);
+ }
+
+ public void active_animation()
+ {
+ add(label_animation, BorderLayout.WEST);
+ DrawPanel.classicMode = DrawPanel.MODE_ANIMATION;
+ mouseAdapt = new MouseAdapter(){
+ public void mouseClicked(MouseEvent e)
+ {
+ stop_animation();
+ cadre.getDrawPanel().repaint();
+ }
+ };
+ label_animation.addMouseListener(mouseAdapt);
+ validate();
+ }
+
+ public void stop_animation()
+ {
+ DrawPanel.classicMode = DrawPanel.MODE_CLASSIC;
+ remove(label_animation);
+ label_animation.removeMouseListener(mouseAdapt);
+ validate();
+ }
+
+ // Change Syntax Highlighting for the editor
+ public void initStyles(int c_comment, int sty_comment, int c_primitive, int sty_primitive, int c_parenthese,
+ int sty_parenthese, int c_operande, int sty_operande)
+ {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ dsd.initStyles(wc.getCommentColor(), wc.getCommentStyle(), wc.getPrimitiveColor(), wc.getPrimitiveStyle(),
+ wc.getBraceColor(), wc.getBraceStyle(), wc.getOperatorColor(), wc.getOperatorStyle());
+ }
+
+ // Enable or disable Syntax Highlighting
+ public void setColoration(boolean b)
+ {
+ dsd.setColoration(b);
+ }
+
+ public void changeFont(Font f)
+ {
+ historique.setFont(f);
+ }
+
+ public void updateText()
+ {
+ historique.setText();
+ }
+
+ public DocumentLogoHistorique getDsd()
+ {
+ return dsd;
+ }
+
+ public StyledDocument sd_Historique()
+ {
+ return historique.getStyledDocument();
+ }
+
+ class Historique extends JTextPane implements ActionListener
+ {
+ private static final long serialVersionUID = 1L;
+ private JPopupMenu popup = new JPopupMenu();
+ private JMenuItem jpopcopier = new JMenuItem();
+ private JMenuItem jpopselect = new JMenuItem();
+ private JMenuItem jpopsave = new JMenuItem();
+
+ Historique()
+ {
+ // this.setBackground(new Color(255,255,220));
+ popup.add(jpopcopier);
+ popup.add(jpopselect);
+ popup.add(jpopsave);
+ jpopselect.addActionListener(this);
+ jpopcopier.addActionListener(this);
+ jpopsave.addActionListener(this);
+ setText();
+ MouseListener popupListener = new MouseAdapter(){
+ public void mouseClicked(MouseEvent e)
+ {
+ if (e.getButton() == 1)
+ {
+ int i = getCaretPosition();
+ int borneinf = borne(i, -1);
+ int bornesup = borne(i, 1);
+ if (borneinf == 0)
+ borneinf = borneinf - 1;
+ select(borneinf + 1, bornesup - 2);
+ cadre.setCommandText(getSelectedText());
+ // historique.setCaretPosition(historique.getDocument().getLength());
+ cadre.focus_Commande();
+ }
+ }
+
+ public void mouseReleased(MouseEvent e)
+ {
+ maybeShowPopup(e);
+ cadre.focus_Commande();
+ }
+
+ public void mousePressed(MouseEvent e)
+ {
+ maybeShowPopup(e);
+ }
+
+ private void maybeShowPopup(MouseEvent e)
+ {
+ if (e.isPopupTrigger())
+ {
+ popup.show(e.getComponent(), e.getX(), e.getY());
+ }
+ }
+ };
+ addMouseListener(popupListener);
+ }
+
+ int borne(int i, int increment)
+ {
+ boolean continuer = true;
+ while (continuer && i != 0)
+ {
+ select(i - 1, i);
+ String t = historique.getSelectedText();
+ if (t.equals("\n"))
+ {
+ continuer = false;
+ }
+ i = i + increment;
+ }
+ return (i);
+ }
+
+ void setText()
+ {
+ jpopselect.setText(Logo.messages.getString("menu.edition.selectall"));
+ jpopcopier.setText(Logo.messages.getString("menu.edition.copy"));
+ jpopsave.setText(Logo.messages.getString("menu.file.textzone.rtf"));
+ jpopselect.setActionCommand(Logo.messages.getString("menu.edition.selectall"));
+ jpopcopier.setActionCommand(Logo.messages.getString("menu.edition.copy"));
+ jpopsave.setActionCommand(Logo.messages.getString("menu.file.textzone.rtf"));
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ UserConfig uc = WSManager.getUserConfig();
+ WorkspaceConfig wc = WSManager.getInstance().getWorkspaceConfigInstance();
+ String cmd = e.getActionCommand();
+ if (Logo.messages.getString("menu.edition.copy").equals(cmd))
+ { // Copier
+ copy();
+ }
+ else if (Logo.messages.getString("menu.edition.selectall").equals(cmd))
+ { // Selectionner tout
+ requestFocus();
+ selectAll();
+ cadre.focus_Commande();
+ }
+ else if (cmd.equals(Logo.messages.getString("menu.file.textzone.rtf")))
+ {
+ RTFEditorKit myRTFEditorKit = new RTFEditorKit();
+ StyledDocument myStyledDocument = getStyledDocument();
+ try
+ {
+ JFileChooser jf = new JFileChooser(Utils.SortieTexte(uc.getDefaultFolder()));
+ String[] ext = { ".rtf" };
+ jf.addChoosableFileFilter(new ExtensionFichier(Logo.messages.getString("fichiers_rtf"), ext));
+ Utils.recursivelySetFonts(jf, wc.getFont());
+ int retval = jf.showDialog(cadre.getFrame(), Logo.messages.getString("menu.file.save"));
+ if (retval == JFileChooser.APPROVE_OPTION)
+ {
+ String path = jf.getSelectedFile().getPath();
+ String path2 = path.toLowerCase(); // on garde la casse
+ // du path pour les
+ // systèmes
+ // d'exploitation
+ // faisant la
+ // différence
+ if (!path2.endsWith(".rtf"))
+ path += ".rtf";
+ FileOutputStream myFileOutputStream = new FileOutputStream(path);
+ myRTFEditorKit.write(myFileOutputStream, myStyledDocument, 0, myStyledDocument.getLength() - 1);
+ myFileOutputStream.close();
+
+ }
+ }
+ catch (FileNotFoundException e1)
+ {}
+ catch (IOException e2)
+ {}
+ catch (BadLocationException e3)
+ {}
+ catch (NullPointerException e4)
+ {}
+ }
+ }
+ }
+
+ public void writeMessage(String messageType, String message)
+ {
+ ecris(messageType, message);
+ }
+}
diff --git a/logo/src/xlogo/gui/Lis.java b/logo/src/xlogo/gui/Lis.java
new file mode 100644
index 0000000..bd6c3ff
--- /dev/null
+++ b/logo/src/xlogo/gui/Lis.java
@@ -0,0 +1,78 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+/**
+ * Title : XLogo
+ * Description : XLogo is an interpreter for the Logo
+ * programming language
+ * @author Loïc Le Coq
+ */
+// Frame for the primitive "read"
+
+
+import javax.swing.JFrame;
+import javax.swing.JTextField;
+import java.awt.HeadlessException;
+import javax.swing.JButton;
+import java.awt.event.*;
+import java.awt.*;
+import xlogo.utils.Utils;
+import xlogo.Logo;
+public class Lis extends JFrame implements ActionListener{
+ private static final long serialVersionUID = 1L;
+ private JTextField texte=new JTextField();
+ private JButton ok=new JButton(Logo.messages.getString("pref.ok"));
+ public Lis() throws HeadlessException {
+ }
+ public Lis(String titre,int longueur){
+ setIconImage(Toolkit.getDefaultToolkit().createImage(Utils.class.getResource("icone.png")));
+ getContentPane().setLayout(new BorderLayout());
+ this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+ getContentPane().add(ok,BorderLayout.EAST);
+ getContentPane().add(texte,BorderLayout.CENTER);
+ texte.setPreferredSize(new Dimension(longueur,50));
+ ok.setPreferredSize(new Dimension(75,50));
+ texte.addActionListener(this);
+ ok.addActionListener(this);
+ pack();
+ setTitle(titre);
+ Dimension d=Toolkit.getDefaultToolkit().getScreenSize().getSize();
+ int x=(int)(d.getWidth()/2-longueur/2);
+ int y=(int)(d.getHeight()/2-25);
+ setLocation(x,y);
+ setVisible(true);
+ texte.requestFocus();
+ }
+ public void actionPerformed(ActionEvent e){
+ setVisible(false);
+ }
+ public String getText(){
+ return texte.getText();
+ }
+} \ No newline at end of file
diff --git a/logo/src/xlogo/gui/MyTextAreaDialog.java b/logo/src/xlogo/gui/MyTextAreaDialog.java
new file mode 100644
index 0000000..fb689ce
--- /dev/null
+++ b/logo/src/xlogo/gui/MyTextAreaDialog.java
@@ -0,0 +1,59 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import java.awt.Color;
+
+import javax.swing.JTextArea;
+
+import xlogo.StyledDocument.DocumentLogoHistorique;
+import xlogo.storage.WSManager;
+/**
+ * This class creates the common yellow JTextArea for all dialog box.
+ * @author loic
+ *
+ */
+public class MyTextAreaDialog extends JTextArea {
+
+ private static final long serialVersionUID = 1L;
+ public MyTextAreaDialog(String message){
+ setText(message);
+ setEditable(false);
+ setBackground(new Color(255,255,177));
+ setFont(WSManager.getWorkspaceConfig().getFont());
+ }
+
+ public MyTextAreaDialog(String message, DocumentLogoHistorique dsd){
+ setFont(dsd.getFont());
+ setText(message);
+ setEditable(false);
+ setBackground(new Color(255,255,177));
+ setFont(WSManager.getWorkspaceConfig().getFont());
+ }
+}
diff --git a/logo/src/xlogo/gui/MyToolBar.java b/logo/src/xlogo/gui/MyToolBar.java
new file mode 100644
index 0000000..bb7afa3
--- /dev/null
+++ b/logo/src/xlogo/gui/MyToolBar.java
@@ -0,0 +1,126 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JToolBar;
+import xlogo.MenuListener;
+import xlogo.utils.Utils;
+
+public class MyToolBar extends JToolBar {
+ private static final long serialVersionUID = 1L;
+ private MenuListener menulistener;
+ private ImageIcon izoomin=Utils.dimensionne_image("zoomin.png",this);
+ private ImageIcon izoomout=Utils.dimensionne_image("zoomout.png",this);
+ private ImageIcon icopier=Utils.dimensionne_image("editcopy.png",this);
+ private ImageIcon icoller=Utils.dimensionne_image("editpaste.png",this);
+ private ImageIcon icouper=Utils.dimensionne_image("editcut.png",this);
+ private ImageIcon iplay=Utils.dimensionne_image("play.png",this);
+ //private ImageIcon iturtleProp=new ImageIcon(Utils.dimensionne_image("turtleProp.png", this));
+ private JButton zoomin=new JButton(izoomin);
+ private JButton zoomout=new JButton(izoomout);
+ private JButton copier=new JButton(icopier);
+ private JButton coller=new JButton(icoller);
+ private JButton couper=new JButton(icouper);
+ private JButton play=new JButton(iplay);
+ //private JButton turtleProp=new JButton(iturtleProp);
+
+
+ public MyToolBar(MenuListener menulistener){
+ super(JToolBar.VERTICAL);
+ this.menulistener=menulistener;
+ initGui();
+ }
+
+ private void initGui(){
+ zoomin.addActionListener(menulistener);
+ zoomin.setActionCommand(MenuListener.ZOOMIN);
+ zoomout.addActionListener(menulistener);
+ zoomout.setActionCommand(MenuListener.ZOOMOUT);
+ copier.addActionListener(menulistener);
+ copier.setActionCommand(MenuListener.EDIT_COPY);
+ couper.addActionListener(menulistener);
+ couper.setActionCommand(MenuListener.EDIT_CUT);
+ coller.addActionListener(menulistener);
+ coller.setActionCommand(MenuListener.EDIT_PASTE);
+ play.addActionListener(menulistener);
+ play.setActionCommand(MenuListener.PLAY);
+/* slider= new JSlider(JSlider.VERTICAL);
+ slider.setValue(slider.getMaximum()-Config.turtleSpeed);
+ //Create the label table
+ Hashtable labelTable = new Hashtable();
+ labelTable.put( new Integer( 0 ), new JLabel("Slow") );
+ labelTable.put( new Integer( 100 ), new JLabel("Fast") );
+ slider.setLabelTable( labelTable );
+ slider.setPaintLabels(true);
+ /* slider.setMajorTickSpacing(10);
+ slider.setMinorTickSpacing(5);
+ slider.setPaintTicks(true);
+
+ slider.setSnapToTicks(true);
+ slider.addChangeListener(new ChangeListener(){
+ public void stateChanged(ChangeEvent e) {
+ JSlider source = (JSlider)e.getSource();
+ int value=source.getValue();
+ Config.turtleSpeed=source.getMaximum()-value;
+ }
+ });
+ int width=Toolkit.getDefaultToolkit().getScreenSize().width;
+ width=32*width/1024;
+ slider.setMinimumSize(new java.awt.Dimension(width,200));
+ slider.setMaximumSize(new java.awt.Dimension(width,200));
+ */
+ add(zoomin);
+ addSeparator();
+ add(zoomout);
+ addSeparator();
+ add(couper);
+ addSeparator();
+ add(copier);
+ addSeparator();
+ add(coller);
+ addSeparator();
+ add(play);
+ addSeparator();
+// add(slider);
+ }
+ public void enabledPlay(boolean b){
+ play.setEnabled(b);
+ }
+ /**
+ * Enables or disables the zoom buttons
+ * @param b The boolean
+ */
+ public void setZoomEnabled(boolean b){
+ zoomin.setEnabled(b);
+ zoomout.setEnabled(b);
+// repaint();
+ }
+}
diff --git a/logo/src/xlogo/gui/ReplaceFrame.java b/logo/src/xlogo/gui/ReplaceFrame.java
new file mode 100644
index 0000000..f51229f
--- /dev/null
+++ b/logo/src/xlogo/gui/ReplaceFrame.java
@@ -0,0 +1,265 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import javax.swing.JDialog;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JRadioButton;
+import javax.swing.JPanel;
+import javax.swing.BoxLayout;
+
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JLabel;
+import javax.swing.ButtonGroup;
+import javax.swing.BorderFactory;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.Highlighter;
+
+import java.awt.event.*;
+
+import javax.swing.JFrame;
+
+import xlogo.Logo;
+import xlogo.storage.WSManager;
+public class ReplaceFrame extends JDialog implements ActionListener{
+ private static final long serialVersionUID = 1L;
+ private final String FIND="find";
+ private final String REPLACE="replace";
+ private final String REPLACEALL="replaceall";
+ private final String FIND_REPLACE="find_replace";
+
+ private JButton find,replace,findReplace,replaceAll;
+ private JRadioButton backward, forward;
+ private JPanel buttonPanel;
+ private JComboBox comboFind,comboReplace;
+ private ButtonGroup bg;
+ private JLabel labelFind, labelReplace,labelResult;
+ private Searchable jtc;
+ Highlighter.HighlightPainter cyanPainter;
+
+ public ReplaceFrame(JFrame jf,Searchable jtc){
+ super(jf);
+ this.jtc=jtc;
+ initGui();
+ }
+
+ public void actionPerformed(ActionEvent e){
+ String cmd=e.getActionCommand();
+ if (cmd.equals(FIND)){
+ find();
+
+ }
+ else if (cmd.equals(REPLACE)){
+ replace();
+ }
+ else if (cmd.equals(FIND_REPLACE)){
+ replace();
+ find();
+ }
+ else if (cmd.equals(REPLACEALL)){
+ replaceAll();
+ }
+
+ }
+ private void replaceAll(){
+ String substitute="";
+ try {
+ substitute=comboReplace.getSelectedItem().toString();
+ addCombo(substitute,comboReplace);
+ }
+ catch(NullPointerException e2){}
+ String element=comboFind.getSelectedItem().toString();
+ addCombo(element,comboFind);
+ jtc.replaceAll(element, substitute);
+ replace.setEnabled(false);
+ findReplace.setEnabled(false);
+
+ }
+ private void replace(){
+ String element=comboReplace.getSelectedItem().toString();
+ addCombo(element,comboReplace);
+ jtc.replace(element,forward.isSelected());
+ replace.setEnabled(false);
+ findReplace.setEnabled(false);
+ }
+ private void find(){
+ String element=comboFind.getSelectedItem().toString();
+ // Add the element to the combobox
+ addCombo(element,comboFind);
+ boolean b=jtc.find(element,forward.isSelected());
+ if (b) {
+ replace.setEnabled(true);
+ findReplace.setEnabled(true);
+ // Found
+ labelResult.setText("");
+ }
+ else {
+ replace.setEnabled(false);
+ findReplace.setEnabled(false);
+ // Not found
+ labelResult.setText(Logo.messages.getString("string_not_found"));
+ }
+ }
+ protected void processWindowEvent(WindowEvent e){
+ super.processWindowEvent(e);
+ if (e.getID()==WindowEvent.WINDOW_CLOSING){
+ jtc.removeHighlight();
+ }
+ }
+ private void addCombo(String element,JComboBox combo){
+ boolean b=false;
+ for (int i=0;i<combo.getItemCount();i++){
+ if (combo.getItemAt(i).equals(element)) {
+ b=true;
+ break;
+ }
+ }
+ if (!b){
+ combo.insertItemAt(element, 0);
+ int n=combo.getItemCount();
+ if (n>10){
+ combo.removeItemAt(n-1);
+ }
+ }
+ }
+ private void setFont(){
+ Font font = WSManager.getWorkspaceConfig().getFont();
+ find.setFont(font);
+ replace.setFont(font);
+ findReplace.setFont(font);
+ replaceAll.setFont(font);
+ backward.setFont(font);
+ forward.setFont(font);
+ comboFind.setFont(font);
+ comboReplace.setFont(font);
+ labelFind.setFont(font);
+ labelReplace.setFont(font);
+ labelResult.setFont(font);
+
+
+ }
+ protected void setText(){
+ setFont();
+ backward=new JRadioButton(Logo.messages.getString("backward"));
+ forward=new JRadioButton(Logo.messages.getString("forward"));
+ TitledBorder tb=BorderFactory.createTitledBorder(Logo.messages.getString("direction"));
+ tb.setTitleFont(WSManager.getWorkspaceConfig().getFont());
+ buttonPanel.setBorder(tb);
+ find=new JButton(Logo.messages.getString("find"));
+ replace=new JButton(Logo.messages.getString("replace"));
+ findReplace=new JButton(Logo.messages.getString("find_replace"));
+ replaceAll=new JButton(Logo.messages.getString("replaceall"));
+ labelFind=new JLabel(Logo.messages.getString("find")+" :");
+ labelReplace=new JLabel(Logo.messages.getString("replacewith"));
+ setTitle(Logo.messages.getString("find_replace"));
+ }
+ private void initGui(){
+
+ setTitle(Logo.messages.getString("find_replace"));
+ // Init the RadioButton for the direction search
+ backward=new JRadioButton(Logo.messages.getString("backward"));
+ forward=new JRadioButton(Logo.messages.getString("forward"));
+ forward.setSelected(true);
+ bg=new ButtonGroup();
+ bg.add(forward);
+ bg.add(backward);
+ buttonPanel=new JPanel();
+ buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.Y_AXIS));
+ buttonPanel.add(forward);
+ buttonPanel.add(backward);
+ TitledBorder tb=BorderFactory.createTitledBorder(Logo.messages.getString("direction"));
+ tb.setTitleFont(WSManager.getWorkspaceConfig().getFont());
+ buttonPanel.setBorder(tb);
+ // Init Buttons
+ find=new JButton(Logo.messages.getString("find"));
+ replace=new JButton(Logo.messages.getString("replace"));
+ findReplace=new JButton(Logo.messages.getString("find_replace"));
+ replaceAll=new JButton(Logo.messages.getString("replaceall"));
+ findReplace.setEnabled(false);
+ replace.setEnabled(false);
+ find.addActionListener(this);
+ findReplace.addActionListener(this);
+ replaceAll.addActionListener(this);
+ replace.addActionListener(this);
+ find.setActionCommand(FIND);
+ replace.setActionCommand(REPLACE);
+ findReplace.setActionCommand(FIND_REPLACE);
+ replaceAll.setActionCommand(REPLACEALL);
+
+ // Init JLabel and JCombobox
+ labelFind=new JLabel(Logo.messages.getString("find")+" :");
+ labelReplace=new JLabel(Logo.messages.getString("replacewith"));
+ labelResult=new JLabel();
+
+ comboFind=new JComboBox();
+ comboReplace=new JComboBox();
+ comboFind.setEditable(true);
+ comboReplace.setEditable(true);
+ setFont();
+ getContentPane().setLayout(new GridBagLayout());
+
+ // Draw all
+
+ getContentPane().add(labelFind, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(comboFind, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(labelReplace, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(comboReplace, new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(buttonPanel, new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(labelResult, new GridBagConstraints(1, 2, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(find, new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(replace, new GridBagConstraints(1, 3, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(findReplace, new GridBagConstraints(0, 4, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(replaceAll, new GridBagConstraints(1, 4, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ }
+}
diff --git a/logo/src/xlogo/gui/SearchFrame.java b/logo/src/xlogo/gui/SearchFrame.java
new file mode 100644
index 0000000..2a177e8
--- /dev/null
+++ b/logo/src/xlogo/gui/SearchFrame.java
@@ -0,0 +1,189 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import javax.swing.JDialog;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JRadioButton;
+import javax.swing.JPanel;
+import javax.swing.BoxLayout;
+
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JLabel;
+import javax.swing.ButtonGroup;
+import javax.swing.BorderFactory;
+import javax.swing.border.TitledBorder;
+import javax.swing.text.Highlighter;
+
+import java.awt.event.*;
+
+import javax.swing.JFrame;
+
+import xlogo.Logo;
+import xlogo.storage.WSManager;
+public class SearchFrame extends JDialog implements ActionListener{
+ private static final long serialVersionUID = 1L;
+ private final String FIND="find";
+
+ private JButton find;
+ private JRadioButton backward, forward;
+ private JPanel buttonPanel;
+ private JComboBox comboFind;
+ private ButtonGroup bg;
+ private JLabel labelFind,labelResult;
+ private Searchable jtc;
+ Highlighter.HighlightPainter cyanPainter;
+
+ public SearchFrame(JFrame jf,Searchable jtc){
+ super(jf);
+ this.jtc=jtc;
+ initGui();
+ }
+
+ public void actionPerformed(ActionEvent e){
+ String cmd=e.getActionCommand();
+ if (cmd.equals(FIND)){
+ find();
+
+ }
+ }
+ private void find(){
+ String element=comboFind.getSelectedItem().toString();
+ // Add the element to the combobox
+ addCombo(element,comboFind);
+ boolean b=jtc.find(element,forward.isSelected());
+ if (b) {
+ // Found
+ labelResult.setText("");
+ }
+ else {
+ // Not found
+ labelResult.setText(Logo.messages.getString("string_not_found"));
+ }
+ }
+ protected void processWindowEvent(WindowEvent e){
+ super.processWindowEvent(e);
+ if (e.getID()==WindowEvent.WINDOW_CLOSING){
+ jtc.removeHighlight();
+ }
+ }
+ private void addCombo(String element,JComboBox combo){
+ boolean b=false;
+ for (int i=0;i<combo.getItemCount();i++){
+ if (combo.getItemAt(i).equals(element)) {
+ b=true;
+ break;
+ }
+ }
+ if (!b){
+ combo.insertItemAt(element, 0);
+ int n=combo.getItemCount();
+ if (n>10){
+ combo.removeItemAt(n-1);
+ }
+ }
+ }
+ protected void setText(){
+ Font font = WSManager.getWorkspaceConfig().getFont();
+ backward.setFont(font);
+ forward.setFont(font);
+ find.setFont(font);
+ labelFind.setFont(font);
+ setFont(font);
+ backward=new JRadioButton(Logo.messages.getString("backward"));
+ forward=new JRadioButton(Logo.messages.getString("forward"));
+ TitledBorder tb=BorderFactory.createTitledBorder(Logo.messages.getString("direction"));
+ tb.setTitleFont(font);
+ buttonPanel.setBorder(tb);
+ find=new JButton(Logo.messages.getString("find"));
+ labelFind=new JLabel(Logo.messages.getString("find")+" :");
+ setTitle(Logo.messages.getString("find_replace"));
+ }
+ private void initGui(){
+ Font font = WSManager.getWorkspaceConfig().getFont();
+
+ setTitle(Logo.messages.getString("find_replace"));
+ // Init the RadioButton for the direction search
+ backward=new JRadioButton(Logo.messages.getString("backward"));
+ forward=new JRadioButton(Logo.messages.getString("forward"));
+ forward.setSelected(true);
+ bg=new ButtonGroup();
+ bg.add(forward);
+ bg.add(backward);
+ buttonPanel=new JPanel();
+ buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.Y_AXIS));
+ buttonPanel.add(forward);
+ buttonPanel.add(backward);
+ TitledBorder tb=BorderFactory.createTitledBorder(Logo.messages.getString("direction"));
+ tb.setTitleFont(font);
+ buttonPanel.setBorder(tb);
+
+ // Init Buttons
+ find=new JButton(Logo.messages.getString("find"));
+ find.addActionListener(this);
+ find.setActionCommand(FIND);
+
+ // Init JLabel and JCombobox
+ labelFind=new JLabel(Logo.messages.getString("find")+" :");
+ labelResult=new JLabel();
+
+ comboFind=new JComboBox();
+ comboFind.setEditable(true);
+
+ backward.setFont(font);
+ forward.setFont(font);
+ find.setFont(font);
+ labelFind.setFont(font);
+ setFont(font);
+
+ getContentPane().setLayout(new GridBagLayout());
+ // Draw all
+
+ getContentPane().add(labelFind, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(comboFind, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(buttonPanel, new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(labelResult, new GridBagConstraints(0, 3, 2, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ getContentPane().add(find, new GridBagConstraints(1, 2, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(
+ 10, 10, 10, 10), 0, 0));
+ }
+}
diff --git a/logo/src/xlogo/gui/Searchable.java b/logo/src/xlogo/gui/Searchable.java
new file mode 100644
index 0000000..2244de8
--- /dev/null
+++ b/logo/src/xlogo/gui/Searchable.java
@@ -0,0 +1,36 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+public interface Searchable {
+ boolean find(String element, boolean forward);
+ void replace(String element,boolean forward);
+ void replaceAll(String element,String substitute);
+ void removeHighlight();
+}
diff --git a/logo/src/xlogo/gui/Traduc.java b/logo/src/xlogo/gui/Traduc.java
new file mode 100644
index 0000000..1c36acc
--- /dev/null
+++ b/logo/src/xlogo/gui/Traduc.java
@@ -0,0 +1,216 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+import javax.swing.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.StringTokenizer;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.TreeMap;
+
+import xlogo.storage.WSManager;
+import xlogo.storage.workspace.Language;
+import xlogo.storage.workspace.WorkspaceConfig;
+import xlogo.utils.Utils;
+import xlogo.Logo;
+/**
+ * Title : XLogo
+ * Description : XLogo is an interpreter for the Logo
+ * programming language
+ * @author Loïc Le Coq
+ */
+
+/** Frame For translating Logo Code from a language to another
+ * * */
+
+public class Traduc extends JFrame implements ActionListener {
+ private static final long serialVersionUID = 1L;
+ private JLabel traduire_de=new JLabel(Logo.messages.getString("traduire_de")+" ");
+ private JLabel vers=new JLabel(" "+Logo.messages.getString("vers")+" ");
+
+ private JComboBox combo_origine=new JComboBox(Logo.translationLanguage);
+ private JComboBox combo_destination=new JComboBox(Logo.translationLanguage);
+ private JScrollPane js_source=new JScrollPane();
+ private JScrollPane js_destination=new JScrollPane();
+ private JTextArea origine=new JTextArea();
+ private JTextArea destination=new JTextArea();
+ private JPanel p_nord_origine =new JPanel();
+ private JPanel p_nord_destination =new JPanel();
+ private JPanel p_ouest =new JPanel();
+ private JPanel p_est=new JPanel();
+ private JPanel p_edition_origine=new JPanel();
+ private JPanel p_edition_destination=new JPanel();
+ private JButton traduire=new JButton(Logo.messages.getString("traduire"));
+ private ImageIcon icopier=Utils.dimensionne_image("editcopy.png",this);
+ private ImageIcon icoller=Utils.dimensionne_image("editpaste.png",this);
+ private ImageIcon icouper=Utils.dimensionne_image("editcut.png",this);
+ private JButton copier_origine=new JButton(icopier);
+ private JButton coller_origine=new JButton(icoller);
+ private JButton couper_origine=new JButton(icouper);
+ private JButton copier_destination=new JButton(icopier);
+ private JButton coller_destination=new JButton(icoller);
+ private JButton couper_destination=new JButton(icouper);
+
+ private ResourceBundle primitives_origine=null;
+ private ResourceBundle primitives_destination=null;
+ private TreeMap<String,String> tre=new TreeMap<String,String>();
+
+ public Traduc(){
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ Font font = wc.getFont();
+ Language lang = wc.getLanguage();
+
+ setTitle(Logo.messages.getString("menu.tools.translate"));
+ setIconImage(Toolkit.getDefaultToolkit().createImage(Utils.class.getResource("icone.png")));
+ setFont(font);
+ traduire.setFont(font);
+ vers.setFont(font);
+ traduire_de.setFont(font);
+ getContentPane().setLayout(new BorderLayout());
+ combo_origine.setSelectedIndex(lang.getValue());
+ combo_destination.setSelectedIndex(lang.getValue());
+
+ p_nord_origine.add(traduire_de);
+ p_nord_origine.add(combo_origine);
+ p_nord_destination.add(vers);
+ p_nord_destination.add(combo_destination);
+
+ p_edition_origine.add(copier_origine);
+ p_edition_origine.add(couper_origine);
+ p_edition_origine.add(coller_origine);
+
+ p_ouest.setLayout(new BorderLayout());
+ p_ouest.add(js_source,BorderLayout.CENTER);
+ p_ouest.add(p_edition_origine,BorderLayout.SOUTH);
+ p_ouest.add(p_nord_origine,BorderLayout.NORTH);
+
+ getContentPane().add(p_ouest,BorderLayout.WEST);
+
+ p_edition_destination.add(copier_destination);
+ p_edition_destination.add(couper_destination);
+ p_edition_destination.add(coller_destination);
+
+ p_est.setLayout(new BorderLayout());
+ p_est.add(js_destination,BorderLayout.CENTER);
+ p_est.add(p_edition_destination,BorderLayout.SOUTH);
+ p_est.add(p_nord_destination,BorderLayout.NORTH);
+
+ getContentPane().add(p_est,BorderLayout.EAST);
+ getContentPane().add(traduire,BorderLayout.CENTER);
+
+ js_source.getViewport().add(origine);
+ js_destination.getViewport().add(destination);
+ js_source.setPreferredSize(new Dimension(300,300));
+ js_destination.setPreferredSize(new Dimension(300,300));
+
+ traduire.addActionListener(this);
+ copier_destination.addActionListener(this);
+ couper_destination.addActionListener(this);
+ coller_destination.addActionListener(this);
+ copier_origine.addActionListener(this);
+ couper_origine.addActionListener(this);
+ coller_origine.addActionListener(this);
+ copier_origine.setActionCommand("copier_origine");
+ couper_origine.setActionCommand("couper_origine");
+ coller_origine.setActionCommand("coller_origine");
+ coller_destination.setActionCommand("coller_destination");
+ copier_destination.setActionCommand("copier_destination");
+ couper_destination.setActionCommand("couper_destination");
+
+ pack();
+ setVisible(true);
+ }
+
+ public void actionPerformed(ActionEvent e){
+ String cmd=e.getActionCommand();
+ if (Logo.messages.getString("traduire").equals(cmd)){
+ String texte=origine.getText();
+ texte=texte.replaceAll("\\t", " ");
+ primitives_origine=genere_langue(combo_origine);
+ primitives_destination=genere_langue(combo_destination);
+ Enumeration<String> en=primitives_origine.getKeys();
+ while (en.hasMoreElements()){
+ String element=en.nextElement().toString();
+ String primitives=primitives_origine.getString(element);
+ String primitives2=primitives_destination.getString(element);
+ StringTokenizer st=new StringTokenizer(primitives);
+ StringTokenizer st2=new StringTokenizer(primitives2);
+ int compteur=st.countTokens();
+ for (int i=0;i<compteur;i++){
+ while (st2.hasMoreTokens()) element=st2.nextToken();
+ tre.put(st.nextToken(),element);
+ }
+ }
+ // ajout des mots clés pour et fin
+ int id=combo_origine.getSelectedIndex();
+ Locale locale=Language.getLanguage(id).getLocale();
+ ResourceBundle res1=ResourceBundle.getBundle("langage",locale);
+ id=combo_destination.getSelectedIndex();
+ locale=Language.getLanguage(id).getLocale();
+ ResourceBundle res2=ResourceBundle.getBundle("langage",locale);
+ tre.put(res1.getString("pour"),res2.getString("pour"));
+ tre.put(res1.getString("fin"),res2.getString("fin"));
+ StringTokenizer st=new StringTokenizer(texte," */+-\n|&()[]",true);
+ String traduc="";
+ while (st.hasMoreTokens()){
+ String element=st.nextToken().toLowerCase();
+ if (tre.containsKey(element)) traduc+=tre.get(element);
+ else traduc+=element;
+ }
+ destination.setText(traduc);
+ }
+ else if ("copier_origine".equals(cmd)) {
+ origine.copy();
+ }
+ else if ("couper_origine".equals(cmd)) {
+ origine.cut();
+ }
+ else if ("coller_origine".equals(cmd)) {
+ origine.paste();
+ }
+ else if ("copier_destination".equals(cmd)) {
+ destination.copy();
+ }
+ else if ("couper_destination".equals(cmd)) {
+ destination.cut();
+ }
+ else if ("coller_destination".equals(cmd)) {
+ destination.paste();
+ }
+ }
+ private ResourceBundle genere_langue(JComboBox jc){ // fixe la langue utilisée pour les messages
+ Locale locale=null;
+ int id=jc.getSelectedIndex();
+ locale=Language.getLanguage(id).getLocale();
+ return ResourceBundle.getBundle("primitives",locale);
+ }
+}
diff --git a/logo/src/xlogo/gui/ZoneCommande.java b/logo/src/xlogo/gui/ZoneCommande.java
new file mode 100644
index 0000000..0bc5f76
--- /dev/null
+++ b/logo/src/xlogo/gui/ZoneCommande.java
@@ -0,0 +1,271 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import javax.swing.JTextPane;
+import javax.swing.SwingUtilities;
+import javax.swing.event.*;
+import javax.swing.text.BadLocationException;
+
+import java.awt.Color;
+
+import xlogo.StyledDocument.DocumentLogoCommande;
+import xlogo.storage.WSManager;
+import xlogo.storage.workspace.WorkspaceConfig;
+import xlogo.Application;
+
+/**
+ * Title : XLogo
+ * Description : XLogo is an interpreter for the Logo
+ * programming language
+ *
+ * @author Loïc Le Coq
+ */
+public class ZoneCommande extends JTextPane implements CaretListener
+{
+ private static final long serialVersionUID = 1L;
+ private DocumentLogoCommande dlc;
+ // Si la correspondance entre parenthese ou crochets est activée
+ private boolean active = false;
+ // Dernière position allumée
+ private int[] position = new int[2];
+
+ public ZoneCommande(Application cadre)
+ {
+ dlc = new DocumentLogoCommande(cadre);
+ this.setBackground(Color.WHITE);
+ setDocument(dlc);
+ addCaretListener(this);
+ }
+
+ class verif_parenthese implements Runnable
+ {
+ int pos;
+
+ verif_parenthese(int pos)
+ {
+ this.pos = pos;
+ }
+
+ public void run()
+ {
+ if (active)
+ {
+ active = false;
+ int debut = position[0];
+ int fin = position[0];
+ if (debut != -1)
+ {
+ if (debut > 0)
+ debut--;
+ if (fin < dlc.getLength())
+ fin++;
+ try
+ {
+ String content = dlc.getText(0, dlc.getLength());
+ // System.out.println(debut+" "+fin);
+ dlc.colore(content, debut, fin);
+ }
+ catch (BadLocationException e)
+ {}
+ }
+ debut = position[1];
+ fin = position[1];
+ if (debut != -1)
+ {
+ if (debut > 0)
+ debut--;
+ if (fin < dlc.getLength())
+ debut++;
+ if (fin < dlc.getLength())
+ fin++;
+ try
+ {
+ String content = dlc.getText(0, dlc.getLength());
+ // System.out.println(debut+" "+fin);
+ dlc.colore(content, debut, fin);
+ }
+ catch (BadLocationException e)
+ {}
+ }
+ }
+ int length = dlc.getLength();
+ try
+ {
+ String content = dlc.getText(pos, length - pos);
+ int id = -1;
+ if (length > pos)
+ {
+ id = "[]()".indexOf(content.substring(0, 1));
+ }
+ if (id > -1 && !TesteBackslash(dlc.getText(0, pos), pos))
+ {
+ active = true;
+ switch (id)
+ {
+ case 0:
+ chercheApres(content, pos, "[", "]");
+ break;
+ case 1:
+ content = getText(0, pos);
+ chercheAvant(content, pos, "[", "]");
+ break;
+ case 2:
+ chercheApres(content, pos, "(", ")");
+ break;
+ case 3:
+ content = getText(0, pos);
+ chercheAvant(content, pos, "(", ")");
+ break;
+ }
+ }
+ }
+ catch (BadLocationException e1)
+ {}
+
+ }
+ }
+
+ public void caretUpdate(CaretEvent e)
+ {
+ int pos = e.getDot();
+ if (WSManager.getWorkspaceConfig().isSyntaxHighlightingEnabled())
+ SwingUtilities.invokeLater(new verif_parenthese(pos));
+ }
+
+ // Teste si le caractère précédent est un backslash
+ private boolean TesteBackslash(String content, int pos)
+ {
+ String caractere = "";
+ if (pos > 0)
+ caractere = content.substring(pos - 1, pos);
+ // System.out.println(caractere);
+ if (caractere.equals("\\"))
+ return true;
+ return false;
+ }
+
+ void chercheApres(String content, int pos, String ouv, String fer)
+ {
+ boolean continuer = true;
+ int of_ouvrant;
+ int of_fermant = 0;
+ int from_index_ouvrant = 1;
+ int from_index_fermant = 1;
+ while (continuer)
+ {
+ of_ouvrant = content.indexOf(ouv, from_index_ouvrant);
+ while (of_ouvrant != -1 && TesteBackslash(content, of_ouvrant))
+ of_ouvrant = content.indexOf(ouv, of_ouvrant + 1);
+ of_fermant = content.indexOf(fer, from_index_fermant);
+ while (of_fermant != -1 && TesteBackslash(content, of_fermant))
+ {
+ of_fermant = content.indexOf(fer, of_fermant + 1);
+ // System.out.println(of_fermant);
+ }
+ if (of_fermant == -1)
+ break;
+ if (of_ouvrant != -1 && of_ouvrant < of_fermant)
+ {
+ from_index_ouvrant = of_ouvrant + 1;
+ from_index_fermant = of_fermant + 1;
+ }
+ else
+ continuer = false;
+ ;
+ }
+ if (of_fermant != -1)
+ {
+ dlc.Montre_Parenthese(of_fermant + pos);
+ position[1] = of_fermant + pos;
+ }
+ else
+ position[1] = -1;
+ dlc.Montre_Parenthese(pos);
+ position[0] = pos;
+ }
+
+ void chercheAvant(String content, int pos, String ouv, String fer)
+ {
+ boolean continuer = true;
+ int of_fermant = 0;
+ int of_ouvrant = 0;
+ int from_index_ouvrant = pos;
+ int from_index_fermant = pos;
+ while (continuer)
+ {
+ of_ouvrant = content.lastIndexOf(ouv, from_index_ouvrant);
+ while (of_ouvrant != -1 && TesteBackslash(content, of_ouvrant))
+ of_ouvrant = content.lastIndexOf(ouv, of_ouvrant - 1);
+ of_fermant = content.lastIndexOf(fer, from_index_fermant);
+ while (of_fermant != -1 && TesteBackslash(content, of_fermant))
+ of_fermant = content.lastIndexOf(fer, of_fermant - 1);
+ if (of_ouvrant == -1)
+ break;
+ if (of_ouvrant < of_fermant)
+ {
+ from_index_ouvrant = of_ouvrant - 1;
+ from_index_fermant = of_fermant - 1;
+ }
+ else
+ continuer = false;
+ ;
+ }
+ if (of_ouvrant != -1)
+ {
+ dlc.Montre_Parenthese(of_ouvrant);
+ position[0] = of_ouvrant;
+ }
+ else
+ position[0] = -1;
+ dlc.Montre_Parenthese(pos);
+ position[1] = pos;
+ }
+
+ // Change Syntax Highlighting for the command line
+ public void initStyles(int c_comment, int sty_comment, int c_primitive, int sty_primitive, int c_parenthese,
+ int sty_parenthese, int c_operande, int sty_operande)
+ {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ dlc.initStyles(wc.getCommentColor(), wc.getCommentStyle(), wc.getPrimitiveColor(), wc.getPrimitiveStyle(),
+ wc.getBraceColor(), wc.getBraceStyle(), wc.getOperatorColor(), wc.getOperatorStyle());
+ }
+
+ // Enable or disable Syntax Highlighting
+ public void setColoration(boolean b)
+ {
+ dlc.setColoration(b);
+ }
+
+ public void setActive(boolean b)
+ {
+ active = b;
+ }
+
+}
diff --git a/logo/src/xlogo/gui/ZoneEdition.java b/logo/src/xlogo/gui/ZoneEdition.java
new file mode 100644
index 0000000..afbda11
--- /dev/null
+++ b/logo/src/xlogo/gui/ZoneEdition.java
@@ -0,0 +1,196 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui;
+
+import javax.swing.event.*;
+import javax.swing.JTextPane;
+import javax.swing.text.BadLocationException;
+import javax.swing.SwingUtilities;
+
+import xlogo.StyledDocument.DocumentLogo;
+import xlogo.storage.WSManager;
+
+/**
+ * Title : XLogo
+ * Description : XLogo is an interpreter for the Logo
+ * programming language
+ * @author Loïc Le Coq
+ */
+class ZoneEdition extends JTextPane implements CaretListener{
+ private static final long serialVersionUID = 1L;
+ private DocumentLogo dsd=null;
+ // Si la correspondance entre parenthese ou crochets est activée
+ private boolean active=false;
+ // Dernière position allumée
+ private int[] position=new int[2];
+
+
+// public DocumentLogo getDsd(){
+// return dsd;
+// }
+ public void setActive(boolean b){
+ active=b;
+ }
+ ZoneEdition(EditorTextPane etp){
+ dsd=etp.getDsd();
+ addCaretListener(this);
+}
+
+// Teste si le caractère précédent est un backslash
+private boolean TesteBackslash(String content,int pos){
+ String caractere="";
+ if (pos>0) caractere=content.substring(pos-1,pos);
+ //System.out.println(caractere);
+ if (caractere.equals("\\")) return true;
+ return false;
+}
+
+class verif_parenthese implements Runnable{
+ int pos;
+ verif_parenthese(int pos){
+ this.pos=pos;
+ }
+ public void run(){
+ if (active){
+ active=false;
+ int debut=position[0];
+ int fin=position[0];
+ if (debut!=-1){
+ if (debut>0) debut--;
+ if (fin<dsd.getLength()) fin++;
+ try{
+ String content=dsd.getText(0,dsd.getLength());
+ dsd.colore(content,debut,fin);
+ }
+ catch(BadLocationException e){}
+ }
+ debut=position[1];
+ fin=position[1];
+ if (debut!=-1){
+ if (debut>0) debut--;
+ if (fin<dsd.getLength()) debut++;
+ if (fin<dsd.getLength()) fin++;
+ try{
+ String content=dsd.getText(0,dsd.getLength());
+ dsd.colore(content,debut,fin);
+ }
+ catch(BadLocationException e){}
+ }
+ }
+ int length=dsd.getLength();
+ try{
+ String content=dsd.getText(pos,length-pos);
+ int id=-1;
+ if (length>pos) {
+ id="[]()".indexOf(content.substring(0,1));
+ }
+ if (id>-1&&!TesteBackslash(dsd.getText(0,pos),pos)){
+ active=true;
+ switch(id){
+ case 0:
+ chercheApres(content,pos,"[","]");
+ break;
+ case 1:
+ content=getText(0,pos);
+ chercheAvant(content,pos,"[","]");
+ break;
+ case 2:
+ chercheApres(content,pos,"(",")");
+ break;
+ case 3:
+ content=getText(0,pos);
+ chercheAvant(content,pos,"(",")");
+ break;
+ }
+ }
+ }
+ catch(BadLocationException e1){}
+
+ }
+}
+public void caretUpdate(CaretEvent e){
+ int pos=e.getDot();
+ if (WSManager.getWorkspaceConfig().isSyntaxHighlightingEnabled()) SwingUtilities.invokeLater(new verif_parenthese(pos));
+}
+ void chercheApres(String content,int pos,String ouv,String fer){
+ boolean continuer=true;
+ int of_ouvrant;
+ int of_fermant=0;
+ int from_index_ouvrant=1;
+ int from_index_fermant=1;
+ while(continuer){
+ of_ouvrant=content.indexOf(ouv,from_index_ouvrant);
+ while (of_ouvrant!=-1&&TesteBackslash(content,of_ouvrant)) of_ouvrant=content.indexOf(ouv,of_ouvrant+1);
+ of_fermant=content.indexOf(fer,from_index_fermant);
+ while (of_fermant!=-1&&TesteBackslash(content,of_fermant)) of_fermant=content.indexOf(fer,of_fermant+1);
+ if (of_fermant==-1) break;
+ if (of_ouvrant!=-1 && of_ouvrant<of_fermant) {
+ from_index_ouvrant=of_ouvrant+1;
+ from_index_fermant=of_fermant+1;
+ }
+ else continuer=false;;
+ }
+ if (of_fermant!=-1) {
+ dsd.Montre_Parenthese(of_fermant+pos);
+ position[1]=of_fermant+pos;
+ }
+ else position[1]=-1;
+ dsd.Montre_Parenthese(pos);
+ position[0]=pos;
+ }
+ void chercheAvant(String content,int pos,String ouv,String fer){
+ boolean continuer=true;
+ int of_fermant=0;
+ int of_ouvrant=0;
+ int from_index_ouvrant=pos;
+ int from_index_fermant=pos;
+ while(continuer){
+ of_ouvrant=content.lastIndexOf(ouv,from_index_ouvrant);
+ while (of_ouvrant!=-1&&TesteBackslash(content,of_ouvrant)) of_ouvrant=content.lastIndexOf(ouv,of_ouvrant-1);
+ of_fermant=content.lastIndexOf(fer,from_index_fermant);
+ while (of_fermant!=-1&&TesteBackslash(content,of_fermant)) of_fermant=content.lastIndexOf(fer,of_fermant-1);
+ if (of_ouvrant==-1) break;
+ if (of_ouvrant<of_fermant) {
+ from_index_ouvrant=of_ouvrant-1;
+ from_index_fermant=of_fermant-1;
+ }
+ else continuer=false;;
+ }
+ if (of_ouvrant!=-1) {
+ dsd.Montre_Parenthese(of_ouvrant);
+ position[0]=of_ouvrant;
+ }
+ else position[0]=-1;
+ dsd.Montre_Parenthese(pos);
+ position[1]=pos;
+
+
+ }
+
+} \ No newline at end of file
diff --git a/logo/src/xlogo/gui/components/ColorStyleSelectionPanel.java b/logo/src/xlogo/gui/components/ColorStyleSelectionPanel.java
new file mode 100644
index 0000000..0e161a2
--- /dev/null
+++ b/logo/src/xlogo/gui/components/ColorStyleSelectionPanel.java
@@ -0,0 +1,232 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * a lot of modifications, extensions, refactorings have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui.components;
+
+import javax.swing.*;
+
+import java.awt.event.*;
+import java.awt.*;
+import java.util.ArrayList;
+
+import xlogo.kernel.DrawPanel;
+import xlogo.Logo;
+
+/**
+ * Title : XLogo Description : XLogo is an interpreter for the Logo programming
+ * language
+ *
+ * @author Loïc Le Coq, Marko refactored
+ */
+public class ColorStyleSelectionPanel {
+
+ private JPanel component = new JPanel();
+
+ public JPanel getComponent()
+ {
+ return component;
+ }
+
+ private Integer[] intArray = new Integer[17];
+ private JButton bchoisir = new JButton(
+ Logo.messages.getString("pref.highlight.other"));
+ private JComboBox combo_couleur;
+ private String[] msg = {
+ Logo.messages.getString("style.none"),
+ Logo.messages.getString("style.bold"),
+ Logo.messages.getString("style.italic"),
+ Logo.messages.getString("style.underline") };
+ private JComboBox style = new JComboBox(msg);
+ private JLabel titre = new JLabel();
+ private Color couleur_perso = Color.WHITE;
+ private GridBagLayout gb = new GridBagLayout();
+
+ public ColorStyleSelectionPanel(int rgb, int sty, String title) {
+ //WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ //Font font = wc.getFont();
+
+ component.setLayout(gb);
+
+ for (int i = 0; i < 17; i++) {
+ intArray[i] = new Integer(i);
+ }
+ // Create the combo box.
+ //titre.setFont(font);
+ titre.setText(title + ":");
+
+ combo_couleur = new JComboBox(intArray);
+ ComboBoxRenderer renderer = new ComboBoxRenderer();
+ combo_couleur.setRenderer(renderer);
+ setColorAndStyle(rgb, sty);
+ combo_couleur.setActionCommand("combo");
+ combo_couleur.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ notifyActionListeners(e);
+ }
+ });
+ //bchoisir.setFont(font);
+ //style.setFont(font);
+ bchoisir.setActionCommand("bouton");
+ bchoisir.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Color color = selectColor();
+ if (null != color) {
+ couleur_perso = color;
+ combo_couleur.setSelectedIndex(7);
+ combo_couleur.repaint();
+ }
+ notifyActionListeners(e);
+ }
+ });
+
+ style.setActionCommand("style");
+ style.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ notifyActionListeners(e);
+ }
+ });
+ //int hauteur = font.getSize() + 5;
+ // jt.setPreferredSize(new Dimension(240,hauteur));
+
+ // Lay out the demo.
+ component.add(combo_couleur, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(5, 5, 5, 5), 0, 0));
+ component.add(bchoisir, new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.NONE,
+ new Insets(5, 5, 5, 5), 0, 0));
+ component.add(style, new GridBagConstraints(2, 1, 1, 1, 1.0, 1.0,
+ GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
+ new Insets(5, 5, 5, 5), 0, 0));
+ component.add(titre, new GridBagConstraints(0, 0, 3, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.VERTICAL,
+ new Insets(5, 5, 0, 5), 0, 0));
+
+ component.setBorder(BorderFactory.createLineBorder(Color.BLUE));
+ //component.setPreferredSize(new Dimension(300, hauteur * 2 + 20));
+ }
+
+ public void setTitle(String title)
+ {
+ titre.setText(title);
+ }
+
+ public void setColorAndStyle(int rgb, int sty) {
+ style.setSelectedIndex(sty);
+ int index = -1;
+ for (int i = 0; i < 17; i++) {
+ if (DrawPanel.defaultColors[i].getRGB() == rgb) {
+ index = i;
+ }
+ }
+ if (index == -1) {
+ couleur_perso = new Color(rgb);
+ index = 7;
+ }
+ combo_couleur.setSelectedIndex(index);
+ }
+
+ private Color selectColor(){
+ return JColorChooser.showDialog(component, "",
+ DrawPanel.defaultColors[combo_couleur.getSelectedIndex()]);
+ }
+
+ private class ComboBoxRenderer extends JPanel implements ListCellRenderer {
+ private static final long serialVersionUID = 1L;
+ int id = 0;
+
+ public ComboBoxRenderer() {
+ setOpaque(true);
+ setPreferredSize(new Dimension(50, 20));
+ }
+
+ public Component getListCellRendererComponent(JList list, Object value,
+ int index, boolean isSelected, boolean cellHasFocus) {
+ // Get the selected index. (The index param isn't
+ // always valid, so just use the value.)
+ int selectedIndex = ((Integer) value).intValue();
+ this.id = selectedIndex;
+ if (isSelected) {
+ setBackground(list.getSelectionBackground());
+ setForeground(list.getSelectionForeground());
+ } else {
+ setBackground(list.getBackground());
+ setForeground(list.getForeground());
+ }
+ // Set the icon and text. If icon was null, say so.
+
+ setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
+ return this;
+ }
+
+ public void paint(Graphics g) {
+ super.paint(g);
+ if (id != 7)
+ g.setColor(DrawPanel.defaultColors[id]);
+ else
+ g.setColor(couleur_perso);
+ g.fillRect(5, 2, 40, 15);
+ }
+ }
+
+ public int color() {
+ int id = combo_couleur.getSelectedIndex();
+ if (id != 7)
+ return DrawPanel.defaultColors[id].getRGB();
+ return couleur_perso.getRGB();
+ }
+
+ public int style() {
+ int id = style.getSelectedIndex();
+ return id;
+ }
+
+ public void setEnabled(boolean b) {
+ component.setEnabled(b);
+ combo_couleur.setEnabled(b);
+ style.setEnabled(b);
+ bchoisir.setEnabled(b);
+ }
+
+
+ private ArrayList<ActionListener> actionListeners = new ArrayList<ActionListener>();
+
+ public void addStyleChangeListener(ActionListener listener)
+ {
+ actionListeners.add(listener);
+ }
+
+ private void notifyActionListeners(ActionEvent e)
+ {
+ for (ActionListener listener : actionListeners)
+ listener.actionPerformed(e);
+ }
+}
diff --git a/logo/src/xlogo/gui/components/ProcedureSearch.java b/logo/src/xlogo/gui/components/ProcedureSearch.java
new file mode 100644
index 0000000..4c01acc
--- /dev/null
+++ b/logo/src/xlogo/gui/components/ProcedureSearch.java
@@ -0,0 +1,309 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.components;
+
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import xlogo.interfaces.ProcedureMapper;
+import xlogo.interfaces.ProcedureMapper.ProcedureMapListener;
+import xlogo.utils.Utils;
+
+public class ProcedureSearch extends JPanel
+{
+ private static final long serialVersionUID = 2275479142269992452L;
+
+ private ProcedureMapper procedureMapper = null;
+
+ private JComboBox procedureSelection = new JComboBox();
+ private JButton procedureSearchButton = new JButton();
+
+ public ProcedureSearch(ProcedureMapper procedureMapper)
+ {
+ this.procedureMapper = procedureMapper;
+ setExecutables(procedureMapper.getAllProcedureNames());
+ initComponents();
+ //applyColorTheme();
+ initListeners();
+ }
+
+ private void initListeners()
+ {
+ procedureMapper.addProcedureMapListener(new ProcedureMapListener(){
+
+ @Override
+ public void ownerRenamed(String oldName, String newName)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ ownerRenamed(oldName, newName);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void defined(String fileName, Collection<String> procedures)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ defined(fileName, procedures);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void defined(String fileName, String procedure)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ defined(fileName, procedure);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void undefined(String fileName, Collection<String> procedures)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ undefined(fileName, procedures);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void undefined(String fileName, String procedure)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ setExecutables(procedureMapper.getAllProcedureNames());
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ undefined(fileName, procedure);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ procedureSearchButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent arg0)
+ {
+ String selected = (String) procedureSelection.getSelectedItem();
+ if (selected == null || selected.length() == 0)
+ return;
+ notifySearchListeners(selected);
+ }
+ });
+
+ procedureSelection.getEditor().addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ String selected = (String) procedureSelection.getSelectedItem();
+ if (selected == null || selected.length() == 0)
+ return;
+ notifySearchListeners(selected);
+ }
+ });
+ }
+
+ private void setExecutables(Collection<String> procedures)
+ {
+ String[] sorted = new String[procedures.size()];
+ sorted = procedures.toArray(sorted);
+ Arrays.sort(sorted);
+
+ procedureSelection.setModel(new DefaultComboBoxModel(sorted));
+ }
+
+ private void initComponents()
+ {
+ procedureSelection.setEditable(true);
+
+ Image img = Toolkit.getDefaultToolkit().getImage(Utils.class.getResource("chercher.png"));
+ procedureSearchButton.setIcon(new ImageIcon(img.getScaledInstance(20, 20, Image.SCALE_SMOOTH)));
+
+ setLayout(new GridBagLayout());
+ GridBagConstraints c = new GridBagConstraints();
+
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1;
+ add(procedureSelection, c);
+
+ c.gridx = 1;
+ c.weightx = 0;
+ add(procedureSearchButton, c);
+ }
+
+ public JComponent getComponent()
+ {
+ return this;
+ }
+
+ @Override
+ public void setFont(Font font)
+ {
+ super.setFont(font);
+ if (procedureSelection != null) // Apparently this became called before object construction...
+ procedureSelection.setFont(font);
+ }
+
+ /*
+ * PROCEDURE SEARCH REQUEST LISTENER
+ */
+
+ public interface ProcedureSearchRequestListener
+ {
+ public void requestProcedureSearch(String procedureName);
+ }
+
+ private ArrayList<ProcedureSearchRequestListener> searchListeners = new ArrayList<ProcedureSearchRequestListener>();
+
+ public void addSearchRequestListener(ProcedureSearchRequestListener listener)
+ {
+ searchListeners.add(listener);
+ }
+
+ public void removeSearchRequestListener(ProcedureSearchRequestListener listener)
+ {
+ searchListeners.remove(listener);
+ }
+
+ private void notifySearchListeners(String procedureName)
+ {
+ for (ProcedureSearchRequestListener listener : searchListeners)
+ listener.requestProcedureSearch(procedureName);
+ }
+}
diff --git a/logo/src/xlogo/gui/components/TurtleComboBox.java b/logo/src/xlogo/gui/components/TurtleComboBox.java
new file mode 100644
index 0000000..952ed7e
--- /dev/null
+++ b/logo/src/xlogo/gui/components/TurtleComboBox.java
@@ -0,0 +1,169 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were adapted by Marko Zivkovic
+ *
+ * The original authors:
+ *
+ * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of Oracle or the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package xlogo.gui.components;
+
+import java.awt.*;
+
+import javax.swing.*;
+
+import xlogo.utils.Utils;
+
+public class TurtleComboBox extends JPanel
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6921667779684536164L;
+ ImageIcon[] images;
+ String[] petStrings = { "preview0", "preview1", "preview2", "preview3", "preview4", "preview5", "preview6" };
+
+ JComboBox petList;
+ /*
+ * Despite its use of EmptyBorder, this panel makes a fine content
+ * pane because the empty border just increases the panel's size
+ * and is "painted" on top of the panel's normal background. In
+ * other words, the JPanel fills its entire background if it's
+ * opaque (which it is by default); adding a border doesn't change
+ * that.
+ */
+ public TurtleComboBox()
+ {
+ super(new BorderLayout());
+
+ //Load the pet images and create an array of indexes.
+ images = new ImageIcon[petStrings.length];
+ Integer[] intArray = new Integer[petStrings.length];
+ for (int i = 0; i < petStrings.length; i++)
+ {
+ intArray[i] = new Integer(i);
+ images[i] = createImageIcon(petStrings[i] + ".png");
+ if (images[i] != null)
+ {
+ images[i].setDescription(petStrings[i]);
+ }
+ }
+
+ //Create the combo box.
+ petList = new JComboBox(intArray);
+ ComboBoxRenderer renderer = new ComboBoxRenderer();
+ renderer.setPreferredSize(new Dimension(50, 50));
+ petList.setRenderer(renderer);
+ petList.setMaximumRowCount(7);
+
+ //Lay out the demo.
+ add(petList, BorderLayout.PAGE_START);
+ setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ }
+
+ public JComboBox getComboBox()
+ {
+ return petList;
+ }
+
+ /** Returns an ImageIcon, or null if the path was invalid. */
+ protected static ImageIcon createImageIcon(String path)
+ {
+ try{
+ return new ImageIcon(Toolkit.getDefaultToolkit().getImage(Utils.class.getResource(path)));
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ class ComboBoxRenderer extends JLabel implements ListCellRenderer
+ {
+
+ private static final long serialVersionUID = -2208613325470559104L;
+
+ public ComboBoxRenderer()
+ {
+ setOpaque(true);
+ setHorizontalAlignment(CENTER);
+ setVerticalAlignment(CENTER);
+ }
+
+ /*
+ * This method finds the image and text corresponding
+ * to the selected value and returns the label, set up
+ * to display the text and image.
+ */
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+ boolean cellHasFocus)
+ {
+ //Get the selected index. (The index param isn't
+ //always valid, so just use the value.)
+ int selectedIndex = ((Integer) value).intValue();
+
+ if (isSelected)
+ {
+ setBackground(list.getSelectionBackground());
+ setForeground(list.getSelectionForeground());
+ }
+ else
+ {
+ setBackground(list.getBackground());
+ setForeground(list.getForeground());
+ }
+
+ //Set the icon and text. If icon was null, say so.
+ ImageIcon icon = images[selectedIndex];
+ setIcon(icon);
+
+ return this;
+ }
+ }
+}
diff --git a/logo/src/xlogo/gui/components/X4SComponent.java b/logo/src/xlogo/gui/components/X4SComponent.java
new file mode 100644
index 0000000..f28341d
--- /dev/null
+++ b/logo/src/xlogo/gui/components/X4SComponent.java
@@ -0,0 +1,81 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.components;
+
+import java.io.File;
+
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+/**
+ * Base Class for well structured GUI components.
+ * includes commonly used features for displaying popups and retrieving user input per dialogs.
+ * @author Marko
+ *
+ */
+public abstract class X4SComponent extends X4SGui{
+
+ public X4SComponent() {
+ super();
+ }
+
+ public abstract JComponent getComponent();
+
+ protected String getUserText(String message, String title)
+ {
+ return (String) JOptionPane.showInputDialog(
+ getComponent(),
+ message,
+ title,
+ JOptionPane.PLAIN_MESSAGE,
+ null,
+ null,
+ null);
+ }
+
+ protected boolean getUserYesOrNo(String message, String title)
+ {
+ int ans = JOptionPane.showConfirmDialog(getComponent(), message, title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+
+ return ans == JOptionPane.YES_OPTION;
+ }
+
+ protected File getUserSelectedDirectory()
+ {
+ final JFileChooser fc = new JFileChooser();
+ fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ int returnVal = fc.showOpenDialog(getComponent());
+
+ if(returnVal == JFileChooser.APPROVE_OPTION)
+ return fc.getSelectedFile();
+ else
+ return null;
+ }
+
+}
diff --git a/logo/src/xlogo/gui/components/X4SFrame.java b/logo/src/xlogo/gui/components/X4SFrame.java
new file mode 100644
index 0000000..92296bb
--- /dev/null
+++ b/logo/src/xlogo/gui/components/X4SFrame.java
@@ -0,0 +1,40 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.components;
+
+import javax.swing.JFrame;
+
+public abstract class X4SFrame extends X4SGui{
+
+ public X4SFrame() {
+ super();
+ }
+
+ public abstract JFrame getFrame();
+
+}
diff --git a/logo/src/xlogo/gui/components/X4SGui.java b/logo/src/xlogo/gui/components/X4SGui.java
new file mode 100644
index 0000000..c0dbc81
--- /dev/null
+++ b/logo/src/xlogo/gui/components/X4SGui.java
@@ -0,0 +1,112 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.components;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import xlogo.AppSettings;
+
+/**
+ * Automatically calls all convenience features in the following order:
+ * <li> initComponent() </li>
+ * <li> layoutComponent() </li>
+ * <li> setText() </li>
+ * <li> initEventListeners() </li>
+ * <li> startListernForLanguageChangeEvents() </li>
+ * <p> Additionally, setText is called when language is changed by the user.
+ * If you do not need to update the language, just {@link X4SGui#stopListenForLanguageChangeEvents()}
+ * @since June 10th 2014
+ * @author Marko
+ */
+public abstract class X4SGui {
+
+ public X4SGui() {
+ initComponent();
+ layoutComponent();
+ setText();
+ initEventListeners();
+ startListenForLanguageChangeEvents();
+ }
+ /**
+ * Subclassses should make sure the component is completely initialized and ready to be used.
+ * Called before setText() and layotComponent()
+ */
+ protected abstract void initComponent();
+
+ protected abstract void layoutComponent();
+
+ protected abstract void initEventListeners();
+
+ public void stopEventListeners()
+ {
+ stopListenForLanguageChangeEvents();
+ }
+
+ private ActionListener languageChangeListener;
+
+ /**
+ * Note: registers only once, even if called more than once.
+ */
+ public void startListenForLanguageChangeEvents()
+ {
+ if (languageChangeListener != null)
+ return;
+ languageChangeListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ setText();
+ }
+ };
+ AppSettings.getInstance().addLanguageChangeListener(languageChangeListener);
+ }
+
+ public void stopListenForLanguageChangeEvents()
+ {
+ if (languageChangeListener == null)
+ return;
+ AppSettings.getInstance().removeLanguageChangeListener(languageChangeListener);
+ languageChangeListener = null;
+ }
+
+ /**
+ * Called whenever language is changed or the component is initialized.
+ */
+ protected void setText() { }
+
+ /**
+ * Shortcut to LanguageManager.getInstance().translate(key)
+ * @param key
+ * @return
+ */
+ protected String translate(String key)
+ {
+ return AppSettings.getInstance().translate(key);
+ }
+
+}
diff --git a/logo/src/xlogo/gui/components/fileslist/11_alerts_and_states_error.png b/logo/src/xlogo/gui/components/fileslist/11_alerts_and_states_error.png
new file mode 100644
index 0000000..097c3bc
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/11_alerts_and_states_error.png
Binary files differ
diff --git a/logo/src/xlogo/gui/components/fileslist/1_navigation_accept.png b/logo/src/xlogo/gui/components/fileslist/1_navigation_accept.png
new file mode 100644
index 0000000..cf5fab3
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/1_navigation_accept.png
Binary files differ
diff --git a/logo/src/xlogo/gui/components/fileslist/5_content_discard.png b/logo/src/xlogo/gui/components/fileslist/5_content_discard.png
new file mode 100644
index 0000000..cedb108
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/5_content_discard.png
Binary files differ
diff --git a/logo/src/xlogo/gui/components/fileslist/5_content_edit.png b/logo/src/xlogo/gui/components/fileslist/5_content_edit.png
new file mode 100644
index 0000000..f09b2e4
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/5_content_edit.png
Binary files differ
diff --git a/logo/src/xlogo/gui/components/fileslist/5_content_remove.png b/logo/src/xlogo/gui/components/fileslist/5_content_remove.png
new file mode 100644
index 0000000..9f4c3d6
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/5_content_remove.png
Binary files differ
diff --git a/logo/src/xlogo/gui/components/fileslist/FilesList.java b/logo/src/xlogo/gui/components/fileslist/FilesList.java
new file mode 100644
index 0000000..eaef2b9
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/FilesList.java
@@ -0,0 +1,665 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.components.fileslist;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+
+import xlogo.Logo;
+import xlogo.interfaces.BasicFileContainer;
+import xlogo.interfaces.BasicFileContainer.FileContainerChangeListener;
+import xlogo.interfaces.BroadcasterErrorFileContainer;
+import xlogo.interfaces.ErrorDetector.FileErrorCollector.ErrorListener;
+import xlogo.interfaces.MessageBroadcaster.MessageListener;
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.gui.components.fileslist.IFilesListItem.ItemRequestHandler;
+
+public class FilesList extends JPanel
+{
+ private static final long serialVersionUID = -3330227288228959914L;
+
+ BroadcasterErrorFileContainer model;
+ FileContainerChangeListener fileContainerModelListener;
+ ErrorListener errorListener;
+ MessageListener messageListener;
+
+ // Handlers
+ private ActionListener addFileRequestHandler;
+ private ItemRequestHandler fileItemRequestHandler;
+
+ // GUI Components
+ /**
+ * The class of file items to use
+ */
+ private Class<? extends IFilesListItem> listItemClass = FilesListItem.class;
+
+ //private JScrollPane scroller;
+ private JButton addFileButton;
+ private Map<String, IFilesListItem> listItems = new HashMap<String, IFilesListItem>();
+
+ private boolean editEnabled = true;
+
+ /*
+ * Init & Model
+ */
+
+ public FilesList(BroadcasterErrorFileContainer fileContainerModel)
+ {
+
+ initComponents();
+ initFileItemListeners();
+ initErrorListener();
+ initFileContainerListener();
+ intitMessageListener();
+ setModel(fileContainerModel);
+ addFileButton.addActionListener(addFileRequestHandler);
+ }
+
+ private void intitMessageListener()
+ {
+ messageListener = new MessageListener(){
+
+ @Override
+ public void messageEvent(final String fileName, final String message)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onMessageEvent(fileName, message);
+ return;
+ }
+
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onMessageEvent(fileName, message);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ messageEvent(fileName, message);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onMessageEvent(String fileName, String message)
+ {
+ IFilesListItem item = listItems.get(fileName);
+ if (item == null)
+ return;
+
+ item.setMessage(message);
+ }
+ };
+ }
+
+ private void initComponents()
+ {
+ this.setOpaque(false);
+
+ Image img = Toolkit.getDefaultToolkit().getImage(getClass().getResource("new_content.png"));
+ addFileButton = new JButton(new ImageIcon(img.getScaledInstance(20, 20, Image.SCALE_SMOOTH)));
+ addFileButton.setOpaque(true);
+
+ setLayout(new GridBagLayout());
+ }
+
+ GridBagConstraints getLayoutConstraints()
+ {
+ GridBagConstraints c = new GridBagConstraints();
+
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.gridx = 0;
+ c.gridy = GridBagConstraints.RELATIVE;
+ c.weightx = 1;
+ return c;
+ }
+
+ private void initFileContainerListener()
+ {
+ fileContainerModelListener = new FileContainerChangeListener(){
+
+ @Override
+ public void fileAdded(final String fileName)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onFileAdded(fileName);
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onFileAdded(fileName);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fileAdded(fileName);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onFileAdded(String fileName)
+ {
+ // On initialization, the files list is fetched using set model
+ // and the events are received, causing a duplication of items in the list.
+ if (listItems.containsKey(fileName))
+ return;
+
+ IFilesListItem item = null;
+ try
+ {
+ item = listItemClass.newInstance();
+ }
+ catch (InstantiationException e)
+ {
+ e.printStackTrace();
+ return;
+ }
+ catch (IllegalAccessException e)
+ {
+ e.printStackTrace();
+ return;
+ }
+ item.setRequestHandler(fileItemRequestHandler);
+ item.setFileName(fileName);
+ item.setEditEnabled(model.isFilesListEditable());
+ item.setError(model.hasErrors(fileName));
+ GridBagConstraints c = getLayoutConstraints();
+ add(item.getComponent(), c);
+ listItems.put(fileName, item);
+ revalidate();
+ }
+
+ @Override
+ public void fileRemoved(final String fileName)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onFileRemoved(fileName);
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onFileRemoved(fileName);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fileRemoved(fileName);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onFileRemoved(String fileName)
+ {
+ IFilesListItem item = listItems.get(fileName);
+ remove(item.getComponent());
+ listItems.remove(fileName);
+ revalidate();
+ validate();
+ }
+
+ @Override
+ public void fileRenamed(final String oldName, final String newName)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onFileRenamed(oldName, newName);
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onFileRenamed(oldName, newName);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fileRenamed(oldName, newName);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onFileRenamed(String oldName, String newName)
+ {
+ IFilesListItem item = listItems.get(oldName);
+ item.setFileName(newName);
+ item.setSelected(true);
+ listItems.remove(oldName);
+ listItems.put(newName, item);
+ item.getComponent().revalidate();
+ }
+
+ /**
+ * This implementation allows multiple files open, if the model decides so.
+ * The Model is responsible to close a specific file before opening another.
+ */
+ @Override
+ public void fileOpened(final String fileName)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onFileOpened(fileName);
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onFileOpened(fileName);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fileOpened(fileName);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onFileOpened(String fileName)
+ {
+ IFilesListItem item = listItems.get(fileName);
+ item.setSelected(true);
+ revalidate();
+ }
+
+ @Override
+ public void fileClosed(final String fileName)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onFileClosed(fileName);
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onFileClosed(fileName);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ fileClosed(fileName);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onFileClosed(String fileName)
+ {
+ IFilesListItem item = listItems.get(fileName);
+ item.setSelected(false);
+ item.getComponent().revalidate();
+ }
+
+ @Override
+ public void editRightsChanged(final boolean enabled)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onEditRightsChanged(enabled);
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onEditRightsChanged(enabled);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ editRightsChanged(enabled);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onEditRightsChanged(boolean enabled)
+ {
+ editEnabled = enabled;
+ if (addFileButton != null)
+ addFileButton.setVisible(editEnabled);
+ for (IFilesListItem item : listItems.values())
+ {
+ item.setEditEnabled(editEnabled);
+ }
+ revalidate();
+ }
+
+ };
+ }
+
+ private void initErrorListener()
+ {
+ errorListener = new ErrorListener(){
+
+ @Override
+ public void errorsDetected(final String fileName)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onErrorsDetected(fileName);
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onErrorsDetected(fileName);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ errorsDetected(fileName);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onErrorsDetected(String fileName)
+ {
+ IFilesListItem item = listItems.get(fileName);
+ if (item == null)
+ return;
+ item.setError(true);
+ item.getComponent().revalidate();
+ }
+
+ @Override
+ public void allErrorsCorrected(final String fileName)
+ {
+ if (SwingUtilities.isEventDispatchThread())
+ {
+ onAllErrorsCorrected(fileName);
+ return;
+ }
+ try
+ {
+ SwingUtilities.invokeAndWait(new Runnable(){
+
+ @Override
+ public void run()
+ {
+ onAllErrorsCorrected(fileName);
+ }
+ });
+ }
+ catch (InterruptedException e)
+ {
+ allErrorsCorrected(fileName);
+ }
+ catch (InvocationTargetException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private void onAllErrorsCorrected(String fileName)
+ {
+ IFilesListItem item = listItems.get(fileName);
+ item.setError(false);
+ item.getComponent().revalidate();
+ }
+ };
+ }
+
+ public void setModel(BroadcasterErrorFileContainer fileContainerModel)
+ {
+ if (this.model != null)
+ {
+ this.model.removeFileListener(fileContainerModelListener);
+ this.model.removeErrorListener(errorListener);
+ this.model.removeBroadcastListener(messageListener);
+ }
+
+ this.model = fileContainerModel;
+
+ if (this.model != null)
+ {
+ this.model.addFileListener(fileContainerModelListener);
+ this.model.addErrorListener(errorListener);
+ this.model.addBroadcastListener(messageListener);
+ }
+
+ initItemsList();
+ }
+
+ /**
+ * Empties the filesList and listItems and then refills them according to the model
+ */
+ private void initItemsList()
+ {
+ listItems.clear();
+ //filesList.removeAll();
+ removeAll();
+ if (model == null)
+ return;
+
+ GridBagConstraints c = getLayoutConstraints();
+
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.gridy = 0;
+ c.weighty = 0;
+ c.weightx = 1;
+ add(addFileButton, c);
+ addFileButton.setVisible(editEnabled);
+
+ for (String fileName : model.getFileNames())
+ fileContainerModelListener.fileAdded(fileName);
+ revalidate();
+ }
+
+ public JComponent getComponent()
+ {
+ return this;
+ }
+
+ public BasicFileContainer getModel()
+ {
+ return model;
+ }
+
+ /*
+ * GETTERS & SETTERS
+ */
+
+ public JScrollPane getScrollPane()
+ {
+ return null;
+ }
+
+ public JButton getAddFileButton()
+ {
+ return addFileButton;
+ }
+
+ protected Map<String, IFilesListItem> getListItems()
+ {
+ return listItems;
+ }
+
+ /**
+ * @param newButton if null, no add button is shown. If this effect is only temporarily wished, use {@link #setEditFilesListEnabled(boolean)}
+ */
+ public void setAddFileButton(JButton newButton)
+ {
+ if (addFileButton != null)
+ {
+ addFileButton.removeActionListener(addFileRequestHandler);
+ //filesList.remove(addFileButton);
+ remove(addFileButton);
+ }
+ if (newButton != null)
+ {
+ newButton.addActionListener(addFileRequestHandler);
+ newButton.setVisible(model.isFilesListEditable());
+ add(newButton);
+ }
+ addFileButton = newButton;
+ revalidate();
+ }
+
+ public void setListItemClass(Class<? extends IFilesListItem> itemClass) throws InstantiationException,
+ IllegalAccessException
+ {
+ if (itemClass == null)
+ throw new IllegalArgumentException("List item class must not be null.");
+
+ this.listItemClass = itemClass;
+
+ initItemsList();
+ }
+
+ // ITEM LISTENERS
+
+ private void initFileItemListeners()
+ {
+ fileItemRequestHandler = new ItemRequestHandler(){
+ @Override
+ public void renameRequest(String oldName, String newName)
+ {
+ model.renameFile(oldName, newName);
+ }
+
+ @Override
+ public void deleteRequest(String fileName)
+ {
+ model.closeFile(fileName);
+ model.removeFile(fileName);
+ }
+
+ @Override
+ public void openRequest(String fileName)
+ {
+ model.openFile(fileName);
+ }
+
+ @Override
+ public void closeRequest(String fileName)
+ {
+ model.closeFile(fileName);
+ }
+ };
+
+ addFileRequestHandler = new ActionListener(){
+
+ @Override
+ public void actionPerformed(ActionEvent event)
+ {
+ String name = model.makeUniqueFileName(Logo.messages.getString("new.file")); // TODO remove dependency
+ try
+ {
+ model.createFile(name);
+ }
+ catch (Exception e)
+ {
+ DialogMessenger.getInstance().dispatchError(Logo.messages.getString("ws.error.title"), // TODO remove dependency
+ Logo.messages.getString("ws.error.could.not.create.logo.file") + "\n" + e.toString());
+ }
+ }
+ };
+ }
+
+}
diff --git a/logo/src/xlogo/gui/components/fileslist/FilesListItem.java b/logo/src/xlogo/gui/components/fileslist/FilesListItem.java
new file mode 100644
index 0000000..33c3934
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/FilesListItem.java
@@ -0,0 +1,542 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.components.fileslist;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.UIManager;
+
+/**
+ * This list item was programmed to provide general methods for a files list.
+ *
+ * However, the component styles could try to follow the current look and feel.
+ * At the moment, style and colors are hard-coded.
+ *
+ * @author Marko Zivkovic
+ */
+public class FilesListItem extends JPanel implements IFilesListItem
+{
+ private static final long serialVersionUID = 3061129268414679076L;
+
+ /*
+ * These are just estimations that are used for getMinimumSize
+ */
+ //private static int MINIMUM_BUTTON_SIZE = 15; // This scales the button icons
+
+ /*
+ * Item State and properties
+ */
+
+ private boolean isEditEnabled = true;
+
+ /**
+ * This is intentionally not included in the State enum (it would double the amount of states),
+ * because it affects only one property
+ */
+ private State state = State.UNSELECTED;
+
+ /**
+ * This enum denotes the different states that FilesListItem can have.
+ * It further provides all necessary state transitions and the state-dependent sizes.
+ * <p>
+ * Note that only properties are modeled here that affect more than one component's properties,
+ * or properties that depend on more than one variable.
+ * @author Marko
+ *
+ */
+ private enum State
+ {
+ UNSELECTED, SELECTED, EDITING,
+ // E prefix <=> File has error
+ E_UNSELECTED, E_SELECTED, E_EDITING;
+
+ /*
+ * State transitions
+ */
+
+ public State selected()
+ {
+ switch(this)
+ {
+ case E_EDITING:
+ case E_SELECTED:
+ case E_UNSELECTED:
+ return State.E_SELECTED;
+ default:
+ return State.SELECTED;
+ }
+ }
+
+ public State unselected()
+ {
+ switch(this)
+ {
+ case E_EDITING:
+ case E_SELECTED:
+ case E_UNSELECTED:
+ return State.E_UNSELECTED;
+ default:
+ return State.UNSELECTED;
+ }
+ }
+
+ public State editing()
+ {
+ switch(this)
+ {
+ case E_EDITING:
+ case E_SELECTED:
+ case E_UNSELECTED:
+ return State.E_EDITING;
+ default:
+ return State.EDITING;
+ }
+ }
+
+ public State withError()
+ {
+ switch(this)
+ {
+ case EDITING:
+ case E_EDITING:
+ return State.E_EDITING;
+ case SELECTED:
+ case E_SELECTED:
+ return State.E_SELECTED;
+ default:
+ return State.E_UNSELECTED;
+ }
+ }
+
+ public State withoutError()
+ {
+ switch(this)
+ {
+ case EDITING:
+ case E_EDITING:
+ return State.EDITING;
+ case SELECTED:
+ case E_SELECTED:
+ return State.SELECTED;
+ default:
+ return State.UNSELECTED;
+ }
+ }
+
+ /*
+ * State dependent component properties
+ */
+
+ public Color getBackgroundColor()
+ {
+ switch(this)
+ {
+ case E_SELECTED:
+ case E_EDITING:
+ return new Color(0xFF6666);
+ case E_UNSELECTED:
+ return new Color(0xFFCCCC);
+ case SELECTED:
+ case EDITING:
+ return new Color(0xDBEBFF);
+ case UNSELECTED:
+ default:
+ return new Color(0xA8CFFF);
+
+ }
+ }
+
+ public Color getBorderColor()
+ {
+ switch(this)
+ {
+ case E_SELECTED:
+ case E_EDITING:
+ return new Color(0xFF4242);
+ case E_UNSELECTED:
+ return new Color(0xFFE0E0);
+ case UNSELECTED:
+ return new Color(0x5BA4FE);
+ default:
+ return new Color(0xEAF4FF);
+
+ }
+ }
+
+ public int getBorderThickness()
+ {
+ switch(this)
+ {
+ case UNSELECTED:
+ case E_UNSELECTED:
+ return 1;
+ default:
+ return 2;
+ }
+ }
+
+ public boolean isSelected()
+ {
+ switch(this)
+ {
+ case E_SELECTED:
+ case SELECTED:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public boolean isEditing()
+ {
+ switch(this)
+ {
+ case E_EDITING:
+ case EDITING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public boolean hasError()
+ {
+ switch(this)
+ {
+ case E_UNSELECTED:
+ case E_SELECTED:
+ case E_EDITING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ }
+
+ /*
+ * Request handler
+ *
+ * Note : this component does not change its state alone.
+ * It only asks the handler to handle some user requests.
+ * It is up to the handler to change the state of this component, based on the result of the request.
+ */
+
+ ItemRequestHandler handler;
+
+ /*
+ * Components
+ */
+
+ private JButton openButton = new JButton();
+ private JButton closeButton = new JButton();
+ private JButton editButton = new JButton();
+ private JButton removeButton = new JButton();
+ private JButton confirmButton = new JButton();
+ private JLabel errorIcon = new JLabel();
+ private JTextField textField = new JTextField();
+ private JLabel messageLabel = new JLabel();
+
+ /*
+ * Constructor & Layout
+ */
+
+ public FilesListItem()
+ {
+
+ closeButton.setIcon(createImageIcon("close_icon2.png", 20, 20));
+ editButton.setIcon(createImageIcon("5_content_edit.png", 20, 20));
+ removeButton.setIcon(createImageIcon("5_content_discard.png", 20, 20));
+ confirmButton.setIcon(createImageIcon("1_navigation_accept.png", 20, 20));
+ errorIcon.setIcon(createImageIcon("11_alerts_and_states_error.png", 20, 20));
+
+ initComponents();
+ initLayout();
+ validate();
+ initComponentListener();
+ }
+
+ public FilesListItem(String fileName, ItemRequestHandler handler)
+ {
+ setFileName(fileName);
+ setRequestHandler(handler);
+ initComponents();
+ initLayout();
+ validate();
+ initComponentListener();
+ }
+
+ private void initLayout()
+ {
+ try
+ {
+ // Apparently, these properties were not set automatically
+ Font font = (Font) UIManager.get("defaultFont");
+ openButton.setFont(font);
+ closeButton.setFont(font);
+ messageLabel.setFont(font);
+ textField.setFont(font);
+ }catch(ClassCastException ignore) {}
+
+ this.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));
+ this.setLayout(new GridBagLayout());
+ GridBagConstraints c = new GridBagConstraints();
+
+ c.fill = GridBagConstraints.BOTH;
+ c.gridx = 0;
+ add(errorIcon, c);
+ add(removeButton, c);
+
+ c.weightx=1; // This is the only one which should extend
+ c.gridx = 1;
+ add(openButton, c);
+ add(closeButton, c);
+ add(textField, c);
+
+ c.weightx=0;
+ c.gridx = 2;
+ add(messageLabel, c);
+
+ c.gridx = 3;
+ add(editButton, c);
+ add(confirmButton, c);
+ }
+
+ private void initComponents()
+ {
+ // The background of this JPanel will be visible below.
+ // => state dependent background color must only be set once
+ openButton.setOpaque(false);
+ closeButton.setOpaque(false);
+ editButton.setOpaque(false);
+ removeButton.setOpaque(false);
+ confirmButton.setOpaque(false);
+ errorIcon.setOpaque(false);
+ messageLabel.setOpaque(false);
+ }
+
+ private void initComponentListener()
+ {
+ openButton.addActionListener(new ActionListener(){
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ if (handler != null)
+ handler.openRequest(openButton.getText());
+ }
+ });
+
+ closeButton.addActionListener(new ActionListener(){
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ if (handler != null)
+ handler.closeRequest(openButton.getText());
+ }
+ });
+
+ editButton.addActionListener(new ActionListener(){
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ state = state.editing();
+ validate();
+ }
+ });
+
+ removeButton.addActionListener(new ActionListener(){
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ if (handler != null)
+ handler.deleteRequest(openButton.getText());
+ }
+ });
+
+ confirmButton.addActionListener(new ActionListener(){
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ String oldName = openButton.getText();
+ String newName = textField.getText();
+
+ if (handler != null && !oldName.equals(newName))
+ handler.renameRequest(oldName, newName);
+ else
+ {
+ state = state.selected();
+ validate();
+ }
+ }
+ });
+
+ textField.addActionListener(new ActionListener(){
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ String oldName = openButton.getText();
+ String newName = textField.getText();
+
+ if (handler != null && !oldName.equals(newName))
+ handler.renameRequest(oldName, newName);
+ else
+ {
+ state = state.selected();
+ validate();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void validate()
+ {
+ super.validate();
+ // First the properties of components are set before super.validate()
+ // Otherwise the changes are not validated, are they?
+ boolean isSelected = state.isSelected();
+ boolean isEditing = state.isEditing();
+ boolean hasError = state.hasError();
+
+ openButton.setVisible(!isSelected && !isEditing);
+ closeButton.setVisible(isSelected);
+ editButton.setVisible(isSelected && isEditEnabled);
+
+ confirmButton.setVisible(isEditing);
+ textField.setVisible(isEditing);
+ removeButton.setVisible(isEditing);
+
+ errorIcon.setVisible(hasError && !isEditing);
+
+ Color backgroundColor = state.getBackgroundColor();
+ setBackground(backgroundColor);
+
+ this.setBorder(BorderFactory.createLineBorder(state.getBorderColor(), state.getBorderThickness()) );
+
+ }
+
+ /*
+ * IFilesListItem
+ */
+
+ @Override
+ public JComponent getComponent()
+ {
+ return this;
+ }
+
+ @Override
+ public void setRequestHandler(ItemRequestHandler handler)
+ {
+ this.handler = handler;
+ validate();
+ }
+
+ @Override
+ public void setFileName(String fileName)
+ {
+ this.openButton.setText(fileName);
+ this.closeButton.setText(fileName);
+ this.textField.setText(fileName);
+ validate();
+ }
+
+ @Override
+ public void setSelected(boolean isSelected)
+ {
+ state = isSelected ? state.selected() : state.unselected();
+ invalidate();
+ validate();
+ }
+
+
+ @Override
+ public void setEditing(boolean isEditing)
+ {
+ state = isEditing ? state.editing() : state.selected();
+ validate();
+ }
+
+ /**
+ * This is used to display the clock per file item in XLogo4Schools
+ * Generally, this can be any message.
+ * @param msg : if null, the message will be hidden, otherwise it is displayed
+ */
+ @Override
+ public void setMessage(String msg)
+ {
+ messageLabel.setVisible(msg != null);
+ messageLabel.setText(msg);
+ validate();
+ }
+
+
+ public String getMessage()
+ {
+ return messageLabel.getText();
+ }
+
+
+ @Override
+ public void setError(boolean hasError)
+ {
+ state = hasError ? state.withError() : state.withoutError();
+ validate();
+ }
+
+
+ public void setEditEnabled(boolean enabled)
+ {
+ isEditEnabled = enabled;
+ validate();
+ }
+
+ /*
+ * Helper
+ */
+ private ImageIcon createImageIcon(String path, int width, int heigth) {
+ Image img = Toolkit.getDefaultToolkit().getImage(getClass().getResource(path));
+ return new ImageIcon(img.getScaledInstance(width, heigth, Image.SCALE_SMOOTH));
+ }
+}
diff --git a/logo/src/xlogo/gui/components/fileslist/IFilesListItem.java b/logo/src/xlogo/gui/components/fileslist/IFilesListItem.java
new file mode 100644
index 0000000..684ec96
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/IFilesListItem.java
@@ -0,0 +1,60 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.components.fileslist;
+
+import javax.swing.JComponent;
+
+public interface IFilesListItem
+{
+ public JComponent getComponent();
+
+ public void setSelected(boolean isSelected);
+
+ public void setEditing(boolean isSelected);
+
+ public void setMessage(String msg);
+
+ public void setError(boolean hasError);
+
+ public void setFileName(String string);
+
+ public void setRequestHandler(ItemRequestHandler handler);
+
+ public void setEditEnabled(boolean enabled);
+
+ public interface ItemRequestHandler
+ {
+ public void openRequest(String fileName);
+
+ public void closeRequest(String fileName);
+
+ public void renameRequest(String oldName, String newName);
+
+ public void deleteRequest(String fileName);
+ }
+}
diff --git a/logo/src/xlogo/gui/components/fileslist/close_icon2.png b/logo/src/xlogo/gui/components/fileslist/close_icon2.png
new file mode 100644
index 0000000..8892697
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/close_icon2.png
Binary files differ
diff --git a/logo/src/xlogo/gui/components/fileslist/new_content.png b/logo/src/xlogo/gui/components/fileslist/new_content.png
new file mode 100644
index 0000000..884c9d2
--- /dev/null
+++ b/logo/src/xlogo/gui/components/fileslist/new_content.png
Binary files differ
diff --git a/logo/src/xlogo/gui/preferences/AbstractPanelColor.java b/logo/src/xlogo/gui/preferences/AbstractPanelColor.java
new file mode 100644
index 0000000..e580526
--- /dev/null
+++ b/logo/src/xlogo/gui/preferences/AbstractPanelColor.java
@@ -0,0 +1,143 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings might have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui.preferences;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JColorChooser;
+import javax.swing.JComboBox;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.ListCellRenderer;
+
+import xlogo.Logo;
+import xlogo.kernel.DrawPanel;
+import xlogo.storage.WSManager;
+
+public abstract class AbstractPanelColor extends JPanel implements ActionListener{
+ private static final long serialVersionUID = 1L;
+// private ImageIcon[] images=new ImageIcon[17];
+ private Integer[] intArray=new Integer[17];
+ private JButton bchoisir=new JButton(Logo.messages.getString("pref.highlight.other"));
+ protected JComboBox combo_couleur;
+ private Color couleur_perso=Color.WHITE;
+ public AbstractPanelColor(Color c) {
+ setBackground(Color.blue);
+ for(int i=0;i<17;i++){
+ intArray[i]=new Integer(i);
+ }
+ combo_couleur = new JComboBox(intArray);
+ ComboBoxRenderer renderer= new ComboBoxRenderer();
+ combo_couleur.setRenderer(renderer);
+ setColorAndStyle(c);
+ combo_couleur.setActionCommand("combo");
+ combo_couleur.addActionListener(this);
+ bchoisir.setFont(WSManager.getWorkspaceConfig().getFont());
+ bchoisir.setActionCommand("bouton");
+ bchoisir.addActionListener(this);
+ add(combo_couleur);
+ add(bchoisir);
+ }
+ public void setEnabled(boolean b){
+ super.setEnabled(b);
+ combo_couleur.setEnabled(b);
+ bchoisir.setEnabled(b);
+
+ }
+ void setColorAndStyle(Color rgb){
+ int index=-1;
+ for(int i=0;i<17;i++){
+ if (DrawPanel.defaultColors[i].equals(rgb)){
+ index=i;
+ }
+ }
+ if (index==-1){couleur_perso=rgb;index=7;}
+ combo_couleur.setSelectedIndex(index);
+ }
+ abstract public void actionPerformed(ActionEvent e);
+
+ private class ComboBoxRenderer extends JPanel
+ implements ListCellRenderer {
+ private static final long serialVersionUID = 1L;
+ int id=0;
+ public ComboBoxRenderer() {
+ setOpaque(true);
+ setPreferredSize(new Dimension(50,20));
+ }
+
+ public Component getListCellRendererComponent(
+ JList list,
+ Object value,
+ int index,
+ boolean isSelected,
+ boolean cellHasFocus) {
+//Get the selected index. (The index param isn't
+//always valid, so just use the value.)
+ int selectedIndex = ((Integer)value).intValue();
+ this.id=selectedIndex;
+ if (isSelected) {
+ setBackground(list.getSelectionBackground());
+ setForeground(list.getSelectionForeground());
+ } else {
+ setBackground(list.getBackground());
+ setForeground(list.getForeground());
+ }
+ //Set the icon and text. If icon was null, say so.
+
+ setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+ return this;
+ }
+ public void paint(Graphics g){
+ super.paint(g);
+ if (id!=7) g.setColor(DrawPanel.defaultColors[id]);
+ else g.setColor(couleur_perso);
+ g.fillRect(5,2,40,15);
+ }
+ }
+ public Color getValue(){
+ int id=combo_couleur.getSelectedIndex();
+ if (id!=7) return DrawPanel.defaultColors[id];
+ return couleur_perso;
+ }
+ protected void actionButton(){
+ Color color=JColorChooser.showDialog(this,"",DrawPanel.defaultColors[combo_couleur.getSelectedIndex()]);
+ if (null!=color){
+ couleur_perso=color;
+ combo_couleur.setSelectedIndex(7);
+ combo_couleur.repaint();
+ }
+ }
+}
diff --git a/logo/src/xlogo/gui/preferences/PanelColor.java b/logo/src/xlogo/gui/preferences/PanelColor.java
new file mode 100644
index 0000000..2fbfe18
--- /dev/null
+++ b/logo/src/xlogo/gui/preferences/PanelColor.java
@@ -0,0 +1,45 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq
+ */
+
+package xlogo.gui.preferences;
+
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+
+public class PanelColor extends AbstractPanelColor{
+
+ private static final long serialVersionUID = 1L;
+ public PanelColor(Color c){
+ super(c);
+ }
+ public void actionPerformed(ActionEvent e){
+ String cmd=e.getActionCommand();
+ if (cmd.equals("bouton")){
+ actionButton();
+ }
+ }
+}
diff --git a/logo/src/xlogo/gui/translation/BottomPanel.java b/logo/src/xlogo/gui/translation/BottomPanel.java
new file mode 100644
index 0000000..bcd98e3
--- /dev/null
+++ b/logo/src/xlogo/gui/translation/BottomPanel.java
@@ -0,0 +1,89 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings migh have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui.translation;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import java.awt.BorderLayout;
+import xlogo.Logo;
+import xlogo.utils.Utils;
+public class BottomPanel extends JPanel {
+ private static final long serialVersionUID = 1L;
+ private TranslateXLogo tx;
+ private JTabbedPane jt;
+ private MyTable messageTable;
+ private MyTable primTable;
+ private String id;
+ private String action;
+ private JButton searchButton;
+ private ImageIcon ichercher=Utils.dimensionne_image("chercher.png",this);
+
+ protected BottomPanel(TranslateXLogo tx,String action, String id){
+ this.tx=tx;
+ this.action=action;
+ this.id=id;
+ initGui();
+ }
+ private void initGui(){
+ setLayout(new BorderLayout());
+ jt= new JTabbedPane();
+ messageTable=new MyTable(tx,action,id,"langage");
+ primTable=new MyTable(tx,action,id,"primitives");
+ jt.add(primTable,Logo.messages.getString("primitives"));
+ jt.add(messageTable,Logo.messages.getString("messages"));
+ javax.swing.JScrollPane scroll=new javax.swing.JScrollPane(jt);
+
+ add(scroll,BorderLayout.CENTER);
+ searchButton=new JButton(ichercher);
+ searchButton.setToolTipText(Logo.messages.getString("find"));
+ searchButton.addActionListener(tx);
+ searchButton.setActionCommand(TranslateXLogo.SEARCH);
+ searchButton.setSize(new java.awt.Dimension(100,50));
+ add(searchButton,BorderLayout.EAST);
+ }
+ protected String getPrimValue(int a, int b){
+ return primTable.getValue(a, b);
+ }
+ protected String getMessageValue(int a, int b){
+ String st=messageTable.getValue(a, b);
+ return st;
+ }
+ protected MyTable getMessageTable(){
+ return this.messageTable;
+ }
+ protected MyTable getPrimTable(){
+ return this.primTable;
+ }
+ protected MyTable getVisibleTable(){
+ if (jt.getSelectedIndex()==0) return primTable;
+ return messageTable;
+ }
+}
diff --git a/logo/src/xlogo/gui/translation/FirstPanel.java b/logo/src/xlogo/gui/translation/FirstPanel.java
new file mode 100644
index 0000000..1fc0309
--- /dev/null
+++ b/logo/src/xlogo/gui/translation/FirstPanel.java
@@ -0,0 +1,237 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings migh have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui.translation;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.ButtonGroup;
+import javax.swing.JRadioButton;
+import javax.swing.JButton;
+import javax.swing.ListCellRenderer;
+import javax.swing.JComboBox;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.MediaTracker;
+import java.awt.Toolkit;
+
+import xlogo.Logo;
+import xlogo.storage.WSManager;
+import xlogo.utils.Utils;
+
+import java.awt.event.*;
+public class FirstPanel extends JPanel implements ActionListener{
+ private static final long serialVersionUID = 1L;
+ private Integer[] intArray;
+
+
+ private JRadioButton consultButton;
+ private JRadioButton modifyButton;
+ private JRadioButton completeButton;
+ private JRadioButton createButton;
+ private JButton validButton;
+ private ButtonGroup group=new ButtonGroup();
+ private JLabel label;
+ private JComboBox comboLangModify;
+ private JComboBox comboLangComplete;
+// private JTextField textLang;
+ private TranslateXLogo tx;
+ protected FirstPanel(TranslateXLogo tx){
+ this.tx=tx;
+ int n=Logo.translationLanguage.length;
+ intArray=new Integer[n];
+ for(int i=0;i<n;i++){
+ intArray[i]=new Integer(i);
+ }
+ initGui();
+ }
+ protected String getAction(){
+ if (modifyButton.isSelected()) return TranslateXLogo.MODIFY;
+ else if (completeButton.isSelected()) return TranslateXLogo.COMPLETE;
+ else if (consultButton.isSelected()) return TranslateXLogo.CONSULT;
+ else if (createButton.isSelected()) return TranslateXLogo.CREATE;
+ return null;
+ }
+ protected String getLang(){
+ if (modifyButton.isSelected()) return String.valueOf(comboLangModify.getSelectedIndex());
+ return String.valueOf(comboLangComplete.getSelectedIndex());
+ }
+/* protected String getNewLang(){
+ return textLang.getText();
+ }*/
+ private void initGui(){
+
+ setLayout(new GridBagLayout());
+
+ // textLang=new JTextField();
+ label=new JLabel(Logo.messages.getString("translatewant"));
+ createButton=new JRadioButton(Logo.messages.getString("translatecreate"));
+ modifyButton=new JRadioButton(Logo.messages.getString("translatemodify"));
+ completeButton=new JRadioButton(Logo.messages.getString("translatecomplete"));
+ consultButton=new JRadioButton(Logo.messages.getString("translateconsult"));
+ createButton.setActionCommand(TranslateXLogo.CREATE);
+ modifyButton.setActionCommand(TranslateXLogo.MODIFY);
+ consultButton.setActionCommand(TranslateXLogo.CONSULT);
+ completeButton.setActionCommand(TranslateXLogo.COMPLETE);
+ createButton.addActionListener(this);
+ completeButton.addActionListener(this);
+ modifyButton.addActionListener(this);
+ consultButton.addActionListener(this);
+ comboLangModify=new JComboBox(intArray);
+ comboLangModify.setRenderer(new Contenu());
+ comboLangComplete=new JComboBox(intArray);
+ comboLangComplete.setRenderer(new Contenu());
+ validButton=new JButton(Logo.messages.getString("pref.ok"));
+ validButton.setActionCommand(TranslateXLogo.OK);
+ validButton.addActionListener(tx);
+ setSize(new java.awt.Dimension(600,120));
+ validButton.setSize(new java.awt.Dimension(100,50));
+ // textLang.setSize(new java.awt.Dimension(100,20));
+
+ group.add(createButton);
+ group.add(modifyButton);
+ group.add(completeButton);
+ group.add(consultButton);
+
+ add(label, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(
+ 0,0,0,0), 0, 0));
+ add(createButton, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(
+ 0,0,0,0), 0, 0));
+ //add(textLang, new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0,
+ // GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(
+ // 0,0,0,0), 0, 0));
+ add(modifyButton, new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(
+ 0,0,0,0), 0, 0));
+ add(comboLangModify, new GridBagConstraints(1, 2, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(
+ 0,0,0,0), 0, 0));
+ add(completeButton, new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(
+ 0,0,0,0), 0, 0));
+ add(comboLangComplete, new GridBagConstraints(1, 3, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(
+ 0,0,0,0), 0, 0));
+ add(consultButton, new GridBagConstraints(0, 4, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(
+ 0,0,0,0), 0, 0));
+ add(validButton, new GridBagConstraints(2, 5, 1, 1, 1.0, 1.0,
+ GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(
+ 0,0,0,0), 0, 0));
+ comboLangComplete.setVisible(false);
+ comboLangModify.setVisible(false);
+ // textLang.setVisible(false);
+
+
+
+ }
+ public void actionPerformed(ActionEvent e){
+ String cmd=e.getActionCommand();
+ if (cmd.equals(TranslateXLogo.MODIFY)){
+ comboLangComplete.setVisible(false);
+ comboLangModify.setVisible(true);
+ // textLang.setVisible(false);
+ }
+ else if (cmd.equals(TranslateXLogo.CREATE)){
+ comboLangComplete.setVisible(false);
+ comboLangModify.setVisible(false);
+ //textLang.setVisible(true);
+ //textLang.validate();
+ }
+ else if (cmd.equals(TranslateXLogo.COMPLETE)){
+ comboLangComplete.setVisible(true);
+ comboLangModify.setVisible(false);
+ //textLang.setVisible(false);
+ }
+ else if (cmd.equals(TranslateXLogo.CONSULT)){
+ comboLangComplete.setVisible(false);
+ comboLangModify.setVisible(false);
+ //textLang.setVisible(false);
+ }
+ }
+
+
+
+ class Contenu extends JLabel implements ListCellRenderer{
+ private static final long serialVersionUID = 1L;
+ private ImageIcon[] drapeau;
+
+ Contenu(){
+ drapeau=new ImageIcon[Logo.translationLanguage.length];
+ cree_icone();
+ }
+ void cree_icone(){
+ for (int i=0;i<drapeau.length;i++){
+ Image image=null;
+ image= Toolkit.getDefaultToolkit().getImage(Utils.class.getResource("drapeau"+i+".png"));
+ MediaTracker tracker=new MediaTracker(this);
+ tracker.addImage(image,0);
+ try{tracker.waitForID(0);}
+ catch(InterruptedException e1){}
+ int largeur=image.getWidth(this);
+ int hauteur=image.getHeight(this);
+ double facteur = (double) WSManager.getWorkspaceConfig().getFont().getSize()/(double)hauteur;
+ image=image.getScaledInstance((int)(facteur*largeur),(int)(facteur*hauteur),Image.SCALE_SMOOTH);
+ tracker=new MediaTracker(this);
+ tracker.addImage(image,0);
+ try{tracker.waitForID(0);}
+ catch(InterruptedException e1){}
+ drapeau[i]=new ImageIcon();
+ drapeau[i].setImage(image);
+// drapeau[i]=new ImageIcon(image);
+ }
+
+ }
+ public Component getListCellRendererComponent(JList list, Object value,int
+ index, boolean isSelected,boolean cellHasFocus){
+ setOpaque(true);
+ int selectedIndex = ((Integer)value).intValue();
+ setText(Logo.translationLanguage[selectedIndex]);
+ setIcon(drapeau[selectedIndex]);
+ if (isSelected) {
+ setBackground(list.getSelectionBackground());
+ setForeground(list.getSelectionForeground()); }
+ else{
+ setBackground(list.getBackground());
+ setForeground(list.getForeground());
+ }
+ setBorder(BorderFactory.createEmptyBorder(5,0,5,5));
+// setEnabled(list.isEnabled());
+ return(this);
+ }
+ }
+
+}
diff --git a/logo/src/xlogo/gui/translation/MyTable.java b/logo/src/xlogo/gui/translation/MyTable.java
new file mode 100644
index 0000000..9976a09
--- /dev/null
+++ b/logo/src/xlogo/gui/translation/MyTable.java
@@ -0,0 +1,375 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings migh have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui.translation;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.awt.Component;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Collections;
+
+import javax.swing.ListSelectionModel;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.AbstractCellEditor;
+import javax.swing.table.TableCellEditor;
+import javax.swing.JTextArea;
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.event.*;
+import javax.swing.JScrollPane;
+
+import java.awt.event.*;
+
+import xlogo.gui.Searchable;
+import xlogo.storage.workspace.Language;
+import xlogo.Logo;
+public class MyTable extends JPanel implements Searchable{
+ private static final long serialVersionUID = 1L;
+ private JTable table;
+ private JScrollPane scrollPane;
+ private TranslateXLogo tx;
+ private String id;
+ private String action;
+ private String bundle;
+ private Vector<String> keys;
+ protected MyTable(TranslateXLogo tx, String action, String id,String bundle){
+ this.tx=tx;
+ this.action=action;
+ this.id=id;
+ this.bundle=bundle;
+ initGui();
+ }
+
+ public void setColumnSize(){
+ for (int i = 0 ; i < table.getColumnCount() ; i++)
+ {
+ table.getColumnModel().getColumn(i).setPreferredWidth(200);
+ }
+ }
+ protected String getValue(int a, int b){
+ return table.getValueAt(a, b).toString();
+ }
+ private void initGui(){
+ setLayout(new java.awt.BorderLayout());
+ table=new JTable(new MyModel(bundle,action,id));
+
+ MultiLineCellEditor editor = new MultiLineCellEditor(table);
+ table.setDefaultEditor(String.class,editor);
+
+ table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+ scrollPane = new JScrollPane(table);
+ //table.setFillsViewportHeight(true);
+ // Only one selection is possible
+ table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ // You can only select Cell
+ table.setCellSelectionEnabled (true);
+ setColumnSize();
+ add(scrollPane,java.awt.BorderLayout.CENTER);
+
+ }
+ protected Vector<String> getKeys(){
+ return keys;
+ }
+ class MultiLineCellEditor extends AbstractCellEditor implements TableCellEditor {
+ private static final long serialVersionUID = 1L;
+ MyTextArea textArea;
+ JTable table;
+
+ public MultiLineCellEditor(JTable ta) {
+ super();
+ table = ta;
+ // this component relies on having this renderer for the String class
+ MultiLineCellRenderer renderer = new MultiLineCellRenderer();
+ table.setDefaultRenderer(String.class,renderer);
+// JOptionPane.showMessageDialog(null,"jui ds l'editor","h",JOptionPane.INFORMATION_MESSAGE);
+ textArea = new MyTextArea();
+ textArea.setLineWrap(true);
+ textArea.setWrapStyleWord(true);
+ for(int i=0;i<table.getRowCount();i++) updateRow(i);
+ }
+
+ /** This method determines the height in pixel of a cell given the text it contains */
+ private int cellHeight(int row,int col) {
+ if (row == table.getEditingRow() && col == table.getEditingColumn())
+ return textArea.getPreferredSize().height;
+ else
+ return table.getDefaultRenderer(String.class).getTableCellRendererComponent(table,
+ table.getModel().getValueAt(row,col),false,false,row,col).getPreferredSize().height;
+ }
+
+ void cellGrewEvent(int row,int column) {
+ updateRow(row);
+ }
+
+ void cellShrankEvent(int row,int column) {
+ updateRow(row);
+ }
+
+ void updateRow(int row) {
+ int maxHeight = 0;
+ for(int j=0;j<table.getColumnCount();j++) {
+ int ch;
+ if ((ch = cellHeight(row,j)) > maxHeight) {
+ maxHeight = ch;
+ }
+ }
+ table.setRowHeight(row,maxHeight);
+ }
+
+ public Object getCellEditorValue() {
+ return textArea.getText();
+ }
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
+ int row, int column) {
+ textArea.setText(table.getValueAt(row,column).toString());
+ textArea.rowEditing = row;
+ textArea.columnEditing = column;
+ textArea.lastPreferredHeight = textArea.getPreferredSize().height;
+
+ return textArea;
+
+ }
+
+ class MyTextArea extends JTextArea implements KeyListener {
+ private static final long serialVersionUID = 1L;
+ int lastPreferredHeight = 0;
+ int rowEditing;
+ int columnEditing;
+
+ MyTextArea() {
+ addKeyListener(this);
+ // This is a fix to Bug Id 4256006
+ addAncestorListener( new AncestorListener(){
+ public void ancestorAdded(AncestorEvent e){
+ requestFocus();
+ }
+ public void ancestorMoved(AncestorEvent e){}
+ public void ancestorRemoved(AncestorEvent e){}
+ });
+ }
+
+ public void keyPressed(KeyEvent e) {}
+ public void keyReleased(KeyEvent e) {}
+ public void keyTyped(KeyEvent e) {
+ if (getPreferredSize().getHeight() > lastPreferredHeight) {
+ lastPreferredHeight = getPreferredSize().height;
+ cellGrewEvent(rowEditing,columnEditing);
+ // this will trigger the addition of extra lines upon the cell growing and
+ // prevent all the text being lost when the cell grows to the point of requiring
+ // scrollbars
+ table.setValueAt(getText(),rowEditing,columnEditing);
+ }
+ else if (getPreferredSize().getHeight() < lastPreferredHeight) {
+ lastPreferredHeight = getPreferredSize().height;
+ cellShrankEvent(rowEditing,columnEditing);
+ }
+ else if (table.getValueAt(rowEditing,columnEditing).equals(""))
+ table.setValueAt(getText(),rowEditing,columnEditing);
+
+ }
+ }
+ }
+
+ class MyModel extends AbstractTableModel {
+ private static final long serialVersionUID = 1L;
+ private String[] columnNames;
+ private String[][] rowData;
+ String action;
+ String id;
+
+ MyModel(String bundle,String action, String id){
+ this.action=action;
+ this.id=id;
+
+ if (action.equals(TranslateXLogo.CREATE)){
+ // Initilaize all Column Names
+ String[] tmp=Logo.translationLanguage;
+ columnNames=new String[tmp.length+1];
+ columnNames[0]=id;
+ for (int i=1;i<columnNames.length;i++){
+ columnNames[i]=tmp[i-1];
+ }
+ }
+ else columnNames=Logo.translationLanguage;
+ buildRowData(bundle, action,id);
+ }
+ public String getColumnName(int col) {
+ return columnNames[col].toString();
+ }
+ public int getRowCount() { return rowData.length; }
+ public int getColumnCount() { return columnNames.length; }
+ public Object getValueAt(int row, int col) {
+ return rowData[row][col];
+ }
+ public boolean isCellEditable(int row, int col)
+ {
+ if (action.equals(TranslateXLogo.CONSULT)) return false;
+ else if (action.equals(TranslateXLogo.CREATE)) {
+ if (col==0) return true;
+ else return false;
+ }
+ else if (action.equals(TranslateXLogo.MODIFY)) {
+ if (col==Integer.parseInt(id)) return true;
+ else return false;
+ }
+ else if (action.equals(TranslateXLogo.COMPLETE)) {
+ if (col==Integer.parseInt(id)) {
+
+ if (rowData[row][col].equals("")) return true;
+ else return false;
+ }
+ else return false;
+ }
+ return true; }
+ public void setValueAt(Object value, int row, int col) {
+ rowData[row][col] = value.toString();
+ fireTableCellUpdated(row, col);
+ }
+ public Class<? extends Object> getColumnClass(int c) {
+ return getValueAt(0, c).getClass();
+
+ }
+
+ private void buildRowData(String bundle,String action, String id){
+ ResourceBundle[] rb=new ResourceBundle[getColumnCount()];
+ // initialize all ResourceBundle
+ for(int i=0;i<getColumnCount();i++){
+ Locale locale = Language.getLanguage(i).getLocale();
+ // In CREATE Mode, when i=getColumnCount(), the last locale is null
+ if (null==locale) break;
+ rb[i] = ResourceBundle.getBundle(bundle, locale);
+ }
+ keys=new Vector<String>();
+ Enumeration<String> en=rb[0].getKeys();
+ while(en.hasMoreElements()){
+ String value=en.nextElement();
+ keys.add(value);
+ }
+ Collections.sort(keys);
+ rowData=new String[keys.size()][getColumnCount()];
+ int row=0;
+ for (int j=0;j<keys.size();j++) {
+ String key=keys.get(j).toString();
+
+ for(int i=0;i<getColumnCount();i++){
+ if (action.equals(TranslateXLogo.CREATE)){
+ if (i==0) rowData[row][0]="";
+ else rowData[row][i]=rb[i-1].getString(key);
+ }
+ else {
+ String element=rb[i].getString(key);
+ if (element.equals("")) {
+ rowData[row][i]="";
+ }
+ else rowData[row][i]=element;
+ }
+ }
+ row++;
+ }
+ }
+ }
+ class MultiLineCellRenderer extends JTextArea implements TableCellRenderer {
+ private static final long serialVersionUID = 1L;
+ public MultiLineCellRenderer() {
+ setEditable(false);
+ setLineWrap(true);
+ setWrapStyleWord(true);
+ }
+
+ public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected, boolean hasFocus, int row, int column) {
+
+ if (value instanceof String) {
+ if (value.toString().equals("")) setBackground(new java.awt.Color(255,200,200));
+ else setBackground(java.awt.Color.WHITE);
+ setText((String)value);
+ if (isSelected) setBackground(java.awt.Color.LIGHT_GRAY);
+ // set the table's row height, if necessary
+ //updateRowHeight(row,getPreferredSize().height);
+ }
+ else
+ setText("");
+ return this;
+ }
+ }
+ int selectedRow=0;
+ int selectedColumn=0;
+ public boolean find(String element,boolean forward){
+ int row=table.getSelectedRow();
+ int col=table.getSelectedColumn();
+ if (row!=-1) {
+ if (row==table.getRowCount()-1) {
+ selectedRow=0;
+ if (col==table.getColumnCount()-1) selectedColumn=0;
+ else selectedColumn=col+1;
+ }
+ else selectedRow=row+1;
+ }
+ int start=selectedRow;
+ for (int c=selectedColumn;c<table.getColumnCount();c++){
+ for(int r=start;r<table.getRowCount();r++){
+ String value=table.getValueAt(r, c).toString();
+ int index=value.indexOf(element);
+ if (index!=-1) {
+ table.clearSelection();
+ if (r==table.getRowCount()-1){
+ selectedRow=0;
+ if (c==table.getColumnCount()-1) selectedColumn=0;
+ else selectedColumn=c+1;
+ }
+ else {
+ selectedRow=r+1;
+ selectedColumn=c;
+ }
+ boolean b=table.editCellAt(r, c);
+ if (!b) {
+ table.changeSelection(r, c,false,false);
+ }
+// System.out.println(selectedRow+" "+selectedColumn);
+ return true;
+ }
+ }
+ start=0;
+ }
+ selectedColumn=0;
+ selectedRow=0;
+ table.changeSelection(0, 0,false,false);
+ return false;
+ }
+ public void replace(String element, boolean forward){
+
+ }
+ public void replaceAll(String element, String substitute){
+
+ }
+ public void removeHighlight(){
+ tx.resetSearchFrame();
+ }
+
+}
diff --git a/logo/src/xlogo/gui/translation/TopPanel.java b/logo/src/xlogo/gui/translation/TopPanel.java
new file mode 100644
index 0000000..239398b
--- /dev/null
+++ b/logo/src/xlogo/gui/translation/TopPanel.java
@@ -0,0 +1,63 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings migh have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui.translation;
+import java.awt.FlowLayout;
+import java.awt.Dimension;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.JButton;
+import xlogo.Logo;
+public class TopPanel extends JPanel {
+ private static final long serialVersionUID = 1L;
+ private TranslateXLogo tx;
+ private JTextArea area;
+ private JButton sendButton;
+ protected TopPanel(TranslateXLogo tx){
+ this.tx=tx;
+ initGui();
+ }
+ private void initGui(){
+ setLayout(new FlowLayout());
+ area=new JTextArea(Logo.messages.getString("translatemessage"));
+ area.setWrapStyleWord(true);
+ area.setLineWrap(true);
+ sendButton=new JButton(Logo.messages.getString("pref.ok"));
+
+
+ area.setEditable(false);
+ sendButton.addActionListener(tx);
+ sendButton.setActionCommand(TranslateXLogo.SEND);
+
+
+ area.setSize(new Dimension(400,100));
+ sendButton.setSize(new Dimension(50,30));
+ add(area);
+ add(sendButton);
+ }
+}
diff --git a/logo/src/xlogo/gui/translation/TranslateXLogo.java b/logo/src/xlogo/gui/translation/TranslateXLogo.java
new file mode 100644
index 0000000..9be2d37
--- /dev/null
+++ b/logo/src/xlogo/gui/translation/TranslateXLogo.java
@@ -0,0 +1,178 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were initially written by Lo�c Le Coq,
+ * modifications, extensions, refactorings migh have been applied by Marko Zivkovic
+ */
+
+package xlogo.gui.translation;
+
+import javax.swing.JFrame;
+import javax.swing.JFileChooser;
+
+import java.awt.BorderLayout;
+import java.awt.Toolkit;
+import java.awt.event.*;
+import java.io.IOException;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import xlogo.Logo;
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.storage.WSManager;
+import xlogo.storage.workspace.Language;
+import xlogo.utils.Utils;
+import xlogo.gui.SearchFrame;
+/**
+ * Modifications made by Marko: <br>
+ * IO error is displayed through DialogMessenger (singleton) instead of {@link Application#ecris()}. Result: This class is completely decoupled from the Application class.
+ * @author lo�c Le Coq, slightly modified by Marko Zivkovic
+ */
+public class TranslateXLogo extends JFrame implements ActionListener {
+ private static final long serialVersionUID = 1L;
+ private String id="";
+ private String action;
+
+ protected static final String OK="ok";
+ protected static final String SEND="send";
+ protected static final String SEARCH="search";
+
+ protected static final String CONSULT="0";
+ protected static final String MODIFY="1";
+ protected static final String CREATE="2";
+ protected static final String COMPLETE="3";
+
+ private FirstPanel first;
+ private TopPanel top;
+ private BottomPanel bottom;
+
+ private SearchFrame sf=null;
+ public TranslateXLogo(){
+ initGui();
+ }
+ private void initGui(){
+ setIconImage(Toolkit.getDefaultToolkit().createImage(
+ Utils.class.getResource("icone.png")));
+ setTitle(Logo.messages.getString("menu.help.translatexlogo"));
+ first=new FirstPanel(this);
+ getContentPane().add(first);
+ setVisible(true);
+ }
+ public void actionPerformed(ActionEvent e){
+ String cmd=e.getActionCommand();
+ if (cmd.equals(TranslateXLogo.OK)){
+ action=first.getAction();
+
+ if (null==action) return;
+ else if (action.equals(TranslateXLogo.MODIFY)) id=first.getLang();
+ else if (action.equals(TranslateXLogo.COMPLETE)) id=first.getLang();
+ //else if (action.equals(TranslateXLogo.CREATE)) id=first.getNewLang();
+ remove(first);
+ bottom=new BottomPanel(this,action,id);
+ getContentPane().setLayout(new BorderLayout());
+ if (!action.equals(TranslateXLogo.CONSULT)){
+ top=new TopPanel(this);
+ getContentPane().add(top,BorderLayout.NORTH);
+
+ }
+
+ getContentPane().add(bottom,BorderLayout.CENTER);
+ this.getContentPane().validate();
+ }
+ else if (cmd.equals(TranslateXLogo.SEND)){
+ String path="";
+ JFileChooser jf=new JFileChooser(Utils.SortieTexte(WSManager.getUserConfig().getDefaultFolder()));
+ int retval=jf.showDialog(this,Logo.messages
+ .getString("menu.file.save"));
+ if (retval==JFileChooser.APPROVE_OPTION){
+ path=jf.getSelectedFile().getPath();
+ StringBuffer sb=new StringBuffer();
+ try {
+ Locale locale=null;
+ if (action.equals(TranslateXLogo.CREATE)){
+ locale = Language.getLanguage(0).getLocale();
+ }
+ else if (!action.equals(TranslateXLogo.CONSULT)){
+ locale = Language.getLanguage(Integer.parseInt(id)).getLocale();
+ }
+ java.util.Vector<String> v=bottom.getPrimTable().getKeys();
+ ResourceBundle rb = ResourceBundle.getBundle("primitives", locale);
+ for (int i=0;i<v.size();i++) {
+ String key=v.get(i);
+ if (action.equals(TranslateXLogo.CREATE)){
+ writeLine(sb,key,bottom.getPrimValue(i,0));
+ }
+ else if (!action.equals(TranslateXLogo.CONSULT)){
+ String element=bottom.getPrimValue(i, Integer.parseInt(id));
+ // System.out.println(element+" clé "+key);
+ if (!rb.getString(key).equals(element)) writeLine(sb,key,element);
+ }
+ }
+ sb.append("\n---------------------------------------\n");
+ v=bottom.getMessageTable().getKeys();
+ rb = ResourceBundle.getBundle("langage", locale);
+ for(int i=0;i<v.size();i++){
+ String key=v.get(i);
+ if (action.equals(TranslateXLogo.CREATE)){
+ writeLine(sb,key,bottom.getMessageValue(i,0).replaceAll("\\n","\\\\n"));
+ }
+ else if (!action.equals(TranslateXLogo.CONSULT)){
+ String element=bottom.getMessageValue(i, Integer.parseInt(id));
+ if (!rb.getString(key).equals(element)) writeLine(sb,key,element.replaceAll("\\n","\\\\n"));
+ }
+ }
+ Utils.writeLogoFile(path,sb.toString());
+ }
+ catch(NullPointerException e3){System.out.println("annulation");} //Si l'utilisateur annule
+ catch(IOException e2){
+ DialogMessenger.getInstance().dispatchError("general.error.title", Logo.messages.getString("error.ioecriture"));
+ }
+ }
+ }
+ else if (cmd.equals(TranslateXLogo.SEARCH)){
+ if (null==sf) {
+ sf=new SearchFrame(this,bottom.getVisibleTable());
+ sf.setSize(350, 350);
+ sf.setVisible(true);
+ }
+ }
+ }
+ protected void resetSearchFrame(){
+ sf=null;
+ }
+ private void writeLine(StringBuffer sb,String key, String value){
+ sb.append(key);
+ sb.append("=");
+ sb.append(value);
+ sb.append("\n");
+
+ }
+ protected void processWindowEvent(WindowEvent e){
+ super.processWindowEvent(e);
+ if (e.getID()==WindowEvent.WINDOW_CLOSING){
+ //app.close_TranslateXLogo(); TODO Application does not need this. Maybe in settings @ welcome
+ }
+
+ }
+}
diff --git a/logo/src/xlogo/gui/welcome/WelcomeScreen.java b/logo/src/xlogo/gui/welcome/WelcomeScreen.java
new file mode 100644
index 0000000..f6e068c
--- /dev/null
+++ b/logo/src/xlogo/gui/welcome/WelcomeScreen.java
@@ -0,0 +1,518 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.welcome;
+import java.awt.event.*;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.JTextComponent;
+
+import java.awt.*;
+import java.io.IOException;
+
+import xlogo.messages.MessageKeys;
+import xlogo.messages.async.AsyncMediumAdapter;
+import xlogo.messages.async.AsyncMessage;
+import xlogo.messages.async.AsyncMessenger;
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.storage.Storable;
+import xlogo.storage.WSManager;
+import xlogo.storage.global.GlobalConfig;
+import xlogo.storage.workspace.WorkspaceConfig;
+import xlogo.utils.Utils;
+import xlogo.utils.WebPage;
+import xlogo.Application;
+import xlogo.Logo;
+
+/**
+ * This was initially called {@code Selection_Langue} and it was only displayed when the Application was opened for the very first time.
+ * Now this has become {@code WelcomeScreen}, as it was enhanced with more options than just language selection:
+ * <li> User Account Selection / Creation </li>
+ * <li> Storage Location (master password required) </li>
+ * @author Marko
+ */
+public class WelcomeScreen extends JFrame {
+ private static final long serialVersionUID = 1L;
+
+ private JLabel label;
+
+ private JLabel workspace = new JLabel("Workspace");
+ private JLabel username = new JLabel("User");
+
+ private JComboBox workspaceSelection = new JComboBox();
+ private JComboBox userSelection = new JComboBox();
+
+ private JButton openWorkspaceSettingsBtn = new JButton("Settings");
+ private JButton enterButton = new JButton("Enter");
+
+ private JButton infoButton = new JButton();
+ private JButton gplButton = new JButton();
+
+ private JPanel panel = new JPanel();
+ private GroupLayout groupLayout;
+
+ private ActionListener listener;
+
+ /**
+ *
+ * @param listener to be informed when the user is ready to enter the application
+ */
+ public WelcomeScreen(ActionListener listener){
+ this.listener = listener;
+ // Window
+ super.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ setIconImage(Toolkit.getDefaultToolkit().createImage(Utils.class.getResource("Icon_x4s.png")));
+ setTitle("XLogo4Schools");
+
+ // The XLogo4Schools logo
+ //ImageIcon logo = Utils.dimensionne_image("Logo_xlogo4schools.png", this);
+
+ infoButton.setIcon(createImageIcon("info_icon.png", "Info", 40, 40));
+ gplButton.setIcon(createImageIcon("gnu_gpl.png", "GPL", 40, 40));
+ label = new JLabel(createImageIcon("Logo_xlogo4schools.png", "XLogo4Schools", 250, 40));
+
+ // Select workspace combo box
+ initWorkspaceListModel();
+ workspaceSelection.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ String workspace = (String) workspaceSelection.getSelectedItem();
+ enterWorkspace(workspace);
+ }
+ });
+ // Open workspace settings button
+ openWorkspaceSettingsBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ showWorkspaceSettings();
+ }
+ });
+
+ // Select user combo box
+ populateUserList();
+ final JTextComponent tc = (JTextComponent) userSelection.getEditor().getEditorComponent();
+ tc.getDocument().addDocumentListener(new DocumentListener() {
+ public void removeUpdate(DocumentEvent arg0) { enableOrDisableEnter(); }
+ public void insertUpdate(DocumentEvent arg0) { enableOrDisableEnter(); }
+ public void changedUpdate(DocumentEvent arg0) { enableOrDisableEnter(); }
+ private void enableOrDisableEnter()
+ {
+ String username = tc.getText();
+ enterButton.setEnabled(username != null && username.length() != 0);
+ }
+ });
+
+ userSelection.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String username = (String) userSelection.getSelectedItem();
+ enterButton.setEnabled(username != null && username.length() != 0);
+ }
+ });
+
+ // Enter user space button
+ enterButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ enterApplication();
+ }
+ });
+
+ gplButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e)
+ {
+ showGPL();
+ }
+ });
+
+ infoButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e)
+ {
+ showInfo();
+ }
+ });
+
+ // Add all
+ initLayout();
+ getContentPane().add(panel);
+ setText();
+ pack();
+ setVisible(true);
+ //MessageManager.getInstance().setParent(this);
+ setMessageManagerParent();
+ }
+
+ private void initWorkspaceListModel()
+ {
+ WSManager wsManager = WSManager.getInstance();
+ try
+ {
+ String lastUsedWorkspace = wsManager.getGlobalConfigInstance().getLastUsedWorkspace();
+ wsManager.enterWorkspace(lastUsedWorkspace);
+ populateWorkspaceList();
+ }
+ catch (IOException e)
+ {
+ DialogMessenger
+ .getInstance()
+ .dispatchMessage(
+ "I'm sorry, something very bad happened",
+ "Please report this error message. You could try to delete the file X4S_GlobalConfig from your home directory, "
+ + "and restart XLogo4Schools. You will have to import your Workspaces again.\n\n"
+ + e.toString());
+ }
+ }
+
+ private void populateWorkspaceList()
+ {
+ GlobalConfig gc = WSManager.getInstance().getGlobalConfigInstance();
+ String[] workspaces = gc.getAllWorkspaces();
+ workspaceSelection.setModel(new DefaultComboBoxModel(workspaces));
+ workspaceSelection.setSelectedItem(gc.getLastUsedWorkspace());
+ }
+
+ private void populateUserList()
+ {
+ WorkspaceConfig wc = WSManager.getInstance().getWorkspaceConfigInstance();
+ String[] users = wc.getUserList();
+ userSelection.setModel(new DefaultComboBoxModel(users));
+ String lastUser = wc.getLastActiveUser();
+ userSelection.setSelectedItem(lastUser);
+ enterButton.setEnabled(lastUser != null && lastUser.length() > 0);
+ userSelection.setEditable(wc.isUserCreationAllowed());
+ }
+
+ protected void enterWorkspace(String workspaceName) {
+ try {
+ WSManager.getInstance().enterWorkspace(workspaceName);
+ populateUserList();
+ } catch (IOException e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ Logo.messages.getString("ws.error.title"),
+ Logo.messages.getString("ws.settings.could.not.enter.wp") + "\n\n" + e.toString());
+ }
+ }
+
+ private void initLayout()
+ {
+ setResizable(false);
+ infoButton.setBorder(null);
+ gplButton.setBorder(null);
+
+ infoButton.setOpaque(false);
+ gplButton.setOpaque(false);
+
+ panel.add(workspace);
+ panel.add(username);
+ panel.add(workspaceSelection);
+ panel.add(userSelection);
+ panel.add(openWorkspaceSettingsBtn);
+ panel.add(enterButton);
+ panel.add(infoButton);
+ panel.add(gplButton);
+
+ workspaceSelection.setMinimumSize(new Dimension(200, 25));
+ userSelection.setMinimumSize(new Dimension(200, 25));
+ workspaceSelection.setMaximumSize(new Dimension(200, 25));
+ userSelection.setMaximumSize(new Dimension(200, 25));
+
+ groupLayout = new GroupLayout(panel);
+ panel.setLayout(groupLayout);
+
+ groupLayout.setAutoCreateGaps(true);
+ groupLayout.setAutoCreateContainerGaps(true);
+
+ groupLayout.setVerticalGroup(
+ groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(gplButton)
+ .addComponent(infoButton)
+ .addComponent(label))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspace)
+ .addComponent(workspaceSelection)
+ .addComponent(openWorkspaceSettingsBtn))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(username)
+ .addComponent(userSelection)
+ .addComponent(enterButton))
+ );
+
+ groupLayout.setHorizontalGroup(
+ groupLayout.createParallelGroup()
+ .addGroup(
+ groupLayout.createSequentialGroup()
+ .addComponent(label)
+ .addComponent(gplButton)
+ .addComponent(infoButton))
+ .addGroup(
+ groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspace)
+ .addComponent(username))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspaceSelection)
+ .addComponent(userSelection))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(openWorkspaceSettingsBtn)
+ .addComponent(enterButton))
+ )
+ );
+ }
+
+ /**
+ * Display {@link xlogo.gui.welcome.WelcomeScreen} when starting the application.
+ */
+ private void showWorkspaceSettings()
+ {
+
+ Runnable runnable = new Runnable() {
+ public void run() {
+ String authentification = null;
+ GlobalConfig gc = WSManager.getInstance().getGlobalConfigInstance();
+ if (gc.isPasswordRequired())
+ {
+ authentification = showPasswordPopup();
+ if (authentification == null)
+ return; // user cancelled the process
+
+ if(!gc.authenticate(new String(authentification)))
+ {
+ // Could not authenticate => cancel
+ DialogMessenger.getInstance().dispatchMessage(
+ Logo.messages.getString("i.am.sorry"),
+ Logo.messages.getString("welcome.wrong.pw"));
+ return;
+ }
+ }
+
+ ActionListener listener = new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ setMessageManagerParent();
+ setText();
+ populateWorkspaceList();
+ populateUserList();
+ setEnabled(true);
+ }
+ };
+
+ setEnabled(false);
+ new WorkspaceSettings(listener, authentification);
+ }
+ };
+
+ new Thread(runnable).start();
+ }
+
+ private void setMessageManagerParent()
+ {
+ DialogMessenger.getInstance().setMedium(new AsyncMediumAdapter<AsyncMessage<JFrame>, JFrame>(){
+ public boolean isReady()
+ {
+ return getThis().isDisplayable();
+ }
+ public JFrame getMedium()
+ {
+ return getThis();
+ }
+ public void addMediumReadyListener(final AsyncMessenger messenger)
+ {
+ getThis().addWindowStateListener(new WindowStateListener(){
+
+ @Override
+ public void windowStateChanged(WindowEvent e)
+ {
+ if (getThis().isDisplayable())
+ messenger.onMediumReady();
+ }
+ });
+ }
+ });
+ }
+
+ private JFrame getThis()
+ {
+ return this;
+ }
+
+
+ protected String showPasswordPopup() {
+ JPasswordField passwordField = new JPasswordField();
+ int option = JOptionPane.showConfirmDialog(this, passwordField, Logo.messages.getString("welcome.enter.pw"),
+ JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
+
+ if (option == JOptionPane.OK_OPTION) {
+ return new String(passwordField.getPassword());
+ }
+ return null;
+ }
+
+ public void enterApplication()
+ {
+ System.gc();
+ String username = (String) userSelection.getSelectedItem();
+
+ if ((username == null) || (username.length() == 0))
+ return; // this should not happen since the enter button is disabled
+
+ if(!Storable.checkLegalName(username))
+ {
+ DialogMessenger.getInstance().dispatchError(
+ Logo.messages.getString(MessageKeys.NAME_ERROR_TITLE),
+ Logo.messages.getString(MessageKeys.ILLEGAL_NAME));
+ return;
+ }
+
+
+ WorkspaceConfig wc = WSManager.getInstance().getWorkspaceConfigInstance();
+ if (!wc.existsUserLogically(username))
+ wc.createUser(username);
+
+ try {
+ WSManager.getInstance().enterUserSpace(username);
+ } catch (IOException e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ Logo.messages.getString("ws.error.title"),
+ Logo.messages.getString("welcome.could.not.enter.user") + e.toString());
+ return;
+ }
+ System.gc();
+ listener.actionPerformed(new ActionEvent(this, 0, null));
+ }
+
+ @Override
+ public void dispose()
+ {
+ try {
+ WSManager.getInstance().getGlobalConfigInstance().store();
+ } catch (IOException e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ Logo.messages.getString("ws.error.title"),
+ Logo.messages.getString("storage.could.not.store.gc"));
+ }
+
+ System.gc();
+ super.dispose();
+ }
+
+ public void setText()
+ {
+ workspace.setText(Logo.messages.getString("welcome.workspace"));
+ username.setText(Logo.messages.getString("welcome.username"));
+ openWorkspaceSettingsBtn.setText(Logo.messages.getString("welcome.settings"));
+ enterButton.setText(Logo.messages.getString("welcome.enter"));
+ setTitle(Logo.messages.getString("welcome.title"));
+ pack();
+ }
+
+ /**
+ * Like in XLogo, almost unmodified.
+ * It is displayed in the language of the currently selected workspace.
+ */
+ private void showGPL()
+ {
+ JFrame frame = new JFrame(Logo.messages.getString("menu.help.licence"));
+ frame.setIconImage(Toolkit.getDefaultToolkit().createImage(WebPage.class.getResource("Logo_xlogo4schools.png")));
+ frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ frame.setSize(500, 500);
+ WebPage editorPane = new WebPage();
+ editorPane.setEditable(false);
+
+ String langCode = WSManager.getWorkspaceConfig().getLanguage().getLanguageCode();
+
+ String path = "gpl/gpl-" + langCode + ".html";
+
+ java.net.URL helpURL = Application.class.getResource(path);
+ if (helpURL != null)
+ {
+ try
+ {
+ editorPane.setPage(helpURL);
+ }
+ catch (IOException e1)
+ {
+ System.err.println("Attempted to read a bad URL: " + helpURL);
+ }
+ }
+ else
+ {
+ System.err.println("Couldn't find file: " + path);
+ }
+
+ // Put the editor pane in a scroll pane.
+ JScrollPane editorScrollPane = new JScrollPane(editorPane);
+ editorScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ editorScrollPane.setPreferredSize(new Dimension(250, 145));
+ editorScrollPane.setMinimumSize(new Dimension(10, 10));
+ frame.getContentPane().add(editorScrollPane);
+ frame.setVisible(true);
+ }
+
+ private void showInfo()
+ {
+ JFrame frame = new JFrame(Logo.messages.getString("menu.help.licence"));
+ frame.setIconImage(Toolkit.getDefaultToolkit().createImage(WebPage.class.getResource("Icon_x4s.png")));
+ frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ frame.setSize(500, 500);
+ WebPage editorPane = new WebPage();
+ editorPane.setEditable(false);
+
+ String path = "gpl/x4s_info.html";
+
+ java.net.URL helpURL = Application.class.getResource(path);
+ if (helpURL != null)
+ {
+ try
+ {
+ editorPane.setPage(helpURL);
+ }
+ catch (IOException e1)
+ {
+ System.err.println("Attempted to read a bad URL: " + helpURL);
+ }
+ }
+ else
+ {
+ System.err.println("Couldn't find file: " + path);
+ }
+
+ // Put the editor pane in a scroll pane.
+ JScrollPane editorScrollPane = new JScrollPane(editorPane);
+ editorScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ editorScrollPane.setPreferredSize(new Dimension(250, 145));
+ editorScrollPane.setMinimumSize(new Dimension(10, 10));
+ frame.getContentPane().add(editorScrollPane);
+ frame.setVisible(true);
+ }
+
+ /*
+ * Helper
+ */
+
+ private ImageIcon createImageIcon(String path, String description, int width, int heigth) {
+ Image img = Toolkit.getDefaultToolkit().getImage(Utils.class.getResource(path));
+ return new ImageIcon(img.getScaledInstance(width, heigth, Image.SCALE_SMOOTH));
+ }
+} \ No newline at end of file
diff --git a/logo/src/xlogo/gui/welcome/WorkspaceSettings.java b/logo/src/xlogo/gui/welcome/WorkspaceSettings.java
new file mode 100644
index 0000000..9634325
--- /dev/null
+++ b/logo/src/xlogo/gui/welcome/WorkspaceSettings.java
@@ -0,0 +1,183 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.welcome;
+
+import java.awt.Toolkit;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowStateListener;
+import java.io.IOException;
+
+import javax.swing.JFrame;
+import javax.swing.JTabbedPane;
+
+import xlogo.gui.components.X4SFrame;
+import xlogo.gui.welcome.settings.tabs.SyntaxHighlightingTab;
+import xlogo.gui.welcome.settings.tabs.ContestTab;
+import xlogo.gui.welcome.settings.tabs.GlobalTab;
+import xlogo.gui.welcome.settings.tabs.WorkspaceTab;
+import xlogo.messages.async.AsyncMediumAdapter;
+import xlogo.messages.async.AsyncMessage;
+import xlogo.messages.async.AsyncMessenger;
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.storage.WSManager;
+import xlogo.utils.Utils;
+
+public class WorkspaceSettings extends X4SFrame {
+
+ private JFrame frame;
+
+ // TABS
+ JTabbedPane tabs;
+ GlobalTab globalTab;
+ WorkspaceTab workspaceTab;
+ SyntaxHighlightingTab appearanceTab;
+ ContestTab contestTab;
+
+ /**
+ * Used to communicate with the frame which opened this one.
+ */
+ private ActionListener listener;
+
+ public WorkspaceSettings(ActionListener listener, String authentification)
+ {
+ super();
+ this.listener = listener;
+ globalTab.authenticate(authentification);
+ frame.setVisible(true);
+ }
+
+ @Override
+ public JFrame getFrame() {
+ return frame;
+ }
+
+ @Override
+ protected void initComponent() {
+ frame = new JFrame(){
+ private static final long serialVersionUID = 7057009528231153055L;
+
+ @Override
+ public void dispose()
+ {
+ try {
+ WSManager.getInstance().getGlobalConfigInstance().store();
+ WSManager.getInstance().getWorkspaceConfigInstance().store();
+ } catch (IOException e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("ws.error.title"),
+ translate("storage.could.not.store.gc"));
+ }
+
+ listener.actionPerformed(null);
+ super.dispose();
+ System.gc();
+ }
+ };
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ frame.setIconImage(Toolkit.getDefaultToolkit().createImage(Utils.class.getResource("Icon_x4s.png"))); // TODO need new icon?
+
+ tabs = new JTabbedPane();
+ globalTab = new GlobalTab();
+ workspaceTab = new WorkspaceTab();
+ appearanceTab = new SyntaxHighlightingTab();
+ contestTab = new ContestTab();
+
+ setMessageManagerParent();
+ }
+
+ @Override
+ protected void layoutComponent() {
+ frame.setResizable(false);
+
+ tabs.addTab("Global", null, globalTab.getComponent(), "Global Settings");
+ tabs.addTab("Workspace", null, workspaceTab.getComponent(), "Workspace Settings");
+ tabs.addTab("Appearance", null, appearanceTab.getComponent(), "Workspace Appearance");
+ tabs.addTab("Contest", null, contestTab.getComponent(), "Contest Settings");
+
+ frame.getContentPane().add(tabs);
+ }
+
+ @Override
+ protected void setText()
+ {
+ frame.setTitle(translate("ws.settings.title"));
+ tabs.setTitleAt(0, translate("ws.settings.global"));
+ tabs.setToolTipTextAt(0, translate("ws.settings.global.settings"));
+ tabs.setTitleAt(1, translate("ws.settings.workspace"));
+ tabs.setToolTipTextAt(1, translate("ws.settings.global.settings"));
+ tabs.setTitleAt(2, translate("ws.settings.syntax")); // TODO make translation
+ tabs.setToolTipTextAt(2, translate("ws.settings.global.settings"));
+ tabs.setTitleAt(3, translate("ws.settings.contest"));
+ tabs.setToolTipTextAt(3, translate("ws.settings.global.settings"));
+ frame.pack();
+ }
+
+ @Override
+ protected void initEventListeners()
+ {
+
+ }
+
+ @Override
+ public void stopEventListeners()
+ {
+ stopListenForLanguageChangeEvents();
+ globalTab.stopEventListeners();
+ workspaceTab.stopEventListeners();
+ appearanceTab.stopEventListeners();
+ contestTab.stopEventListeners();
+ }
+
+ private void setMessageManagerParent()
+ {
+ DialogMessenger.getInstance().setMedium(new AsyncMediumAdapter<AsyncMessage<JFrame>, JFrame>(){
+ public boolean isReady()
+ {
+ return frame.isDisplayable();
+ }
+ public JFrame getMedium()
+ {
+ return frame;
+ }
+ public void addMediumReadyListener(final AsyncMessenger messenger)
+ {
+ frame.addWindowStateListener(new WindowStateListener(){
+
+ @Override
+ public void windowStateChanged(WindowEvent e)
+ {
+ if (frame.isDisplayable())
+ messenger.onMediumReady();
+ }
+ });
+ }
+ });
+ }
+
+}
diff --git a/logo/src/xlogo/gui/welcome/settings/tabs/AbstractWorkspacePanel.java b/logo/src/xlogo/gui/welcome/settings/tabs/AbstractWorkspacePanel.java
new file mode 100644
index 0000000..a226e64
--- /dev/null
+++ b/logo/src/xlogo/gui/welcome/settings/tabs/AbstractWorkspacePanel.java
@@ -0,0 +1,269 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.welcome.settings.tabs;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JOptionPane;
+
+import xlogo.AppSettings;
+import xlogo.gui.components.X4SComponent;
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.storage.Storable;
+import xlogo.storage.WSManager;
+import xlogo.storage.global.GlobalConfig;
+import xlogo.storage.workspace.WorkspaceConfig;
+
+public abstract class AbstractWorkspacePanel extends X4SComponent{
+
+ private ActionListener enterWorkspaceListener;
+ private ActionListener workspaceListChangeListener;
+
+ protected abstract JComboBox getWorkspaceSelection();
+
+ @Override
+ protected void initEventListeners()
+ {
+ getWorkspaceSelection().addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ new Thread(new Runnable() {
+ public void run() {
+ String wsName = (String) getWorkspaceSelection().getSelectedItem();
+ enterWorkspace(wsName);
+ }
+ }).run();
+ }
+ });
+
+ final GlobalConfig gc = WSManager.getGlobalConfig();
+
+ gc.addWorkspaceListChangeListener(workspaceListChangeListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ populateWorkspaceList();
+ }
+ });
+
+ gc.addEnterWorkspaceListener(enterWorkspaceListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ getWorkspaceSelection().setSelectedItem(gc.getLastUsedWorkspace());
+ }
+ });
+ }
+
+ @Override
+ public void stopEventListeners()
+ {
+ super.stopEventListeners();
+ GlobalConfig gc = WSManager.getGlobalConfig();
+ gc.removeEnterWorkspaceListener(enterWorkspaceListener);
+ gc.removeWorkspaceListChangeListener(workspaceListChangeListener);
+
+ }
+ protected abstract void setValues();
+
+ protected abstract void enableComponents();
+
+ protected abstract void disableComponents();
+
+ protected void populateWorkspaceList() {
+ GlobalConfig gc = WSManager.getInstance().getGlobalConfigInstance();
+ String[] workspaces = gc.getAllWorkspaces();
+ getWorkspaceSelection().setModel(new DefaultComboBoxModel(workspaces));
+ String lastUsed = gc.getLastUsedWorkspace();
+ enterWorkspace(lastUsed);
+ getWorkspaceSelection().setSelectedItem(lastUsed);
+ }
+
+ protected void deleteWorkspace() {
+ WSManager wsManager = WSManager.getInstance();
+ GlobalConfig gc = wsManager.getGlobalConfigInstance();
+
+ String wsName = (String) getWorkspaceSelection().getSelectedItem();
+ String wsLocation = gc.getWorkspaceDirectory(wsName).toString();
+ String message =
+ translate("ws.settings.want.delete.dir.1")
+ + wsLocation
+ + translate("ws.settings.want.delete.dir.2");
+
+ boolean ans = getUserYesOrNo(message, translate("ws.settings.delete.from.fs"));
+
+ try {
+ wsManager.enterWorkspace(WorkspaceConfig.VIRTUAL_WORKSPACE);
+ } catch (IOException e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("ws.error.title"),
+ translate("ws.settings.could.not.enter.virtual.ws") + e.toString());
+ }
+ wsManager.deleteWorkspace(wsName, ans);
+
+ populateWorkspaceList();
+ }
+
+ protected void importWorkspace() {
+ File dir = getUserSelectedDirectory();
+ if (dir == null)
+ return;
+
+ WSManager wsManager = WSManager.getInstance();
+ if (!WSManager.isWorkspaceDirectory(dir))
+ {
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("i.am.sorry"),
+ dir.toString() + translate("ws.settings.not.legal.ws.dir"));
+ return;
+ }
+ String newName = dir.getName();
+
+ if (dir.equals(WSManager.getGlobalConfig().getWorkspaceDirectory(newName)))
+ {
+ DialogMessenger.getInstance().dispatchMessage("The workspace was already in the list.");
+ return;
+ }
+
+ File newDir = new File(dir.toString());
+
+ if (WSManager.getGlobalConfig().existsWorkspace(newName) || !Storable.checkLegalName(newName))
+ {
+ do
+ {
+ String msg = WSManager.getGlobalConfig().existsWorkspace(newName) ?
+ "The workspace name " + newName + " already exists. Please choose a new name"
+ : newDir.exists() ? newDir.toString() + " already exists. Please choose a new name."
+ : "The chosen name contains illegal characters.";
+
+ newName = getUserText(msg, "Name Conflict");
+ if (newName == null)
+ return;
+
+ newDir = new File(dir.getParent() + File.separator + newName);
+ }
+ while(WSManager.getGlobalConfig().existsWorkspace(newName)
+ || !Storable.checkLegalName(newName)
+ || newDir.exists());
+ }
+
+ if(!newDir.equals(dir))
+ dir.renameTo(newDir);
+
+ wsManager.importWorkspace(newDir, newName);
+ populateWorkspaceList();
+ }
+
+ protected void enterWorkspace(String wsName) {
+ try {
+ // enter workspace
+ WSManager.getInstance().enterWorkspace(wsName);
+ WorkspaceConfig wc = WSManager.getInstance().getWorkspaceConfigInstance();
+ if (wc == null)
+ {
+ disableComponents();
+ return;
+ }
+ if (wc.isVirtual())
+ disableComponents();
+ else
+ enableComponents();
+ setValues();
+ AppSettings.getInstance().setLanguage(wc.getLanguage());
+ } catch (IOException e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("ws.error.title"),
+ translate("ws.settings.could.not.enter.wp") + e.toString());
+ disableComponents();
+ }
+
+ }
+
+ protected void addWorkspace() {
+ WorkspaceCreationPanel wscPanel = new WorkspaceCreationPanel();
+
+ int option = JOptionPane.showConfirmDialog(
+ getComponent(),
+ wscPanel.getComponent(),
+ translate("ws.settings.create.new.wp"),
+ JOptionPane.OK_CANCEL_OPTION,
+ JOptionPane.PLAIN_MESSAGE);
+
+ if (option != JOptionPane.OK_OPTION)
+ return;
+
+ String wsName = wscPanel.wsNameField.getText();
+ String location = wscPanel.locationField.getText();
+ File dir = new File(location);
+
+ GlobalConfig gc = WSManager.getInstance().getGlobalConfigInstance();
+
+ // Make sure that the specified workspace name is non-empty and that it does not exist already
+ if (wsName.length() == 0){
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("i.am.sorry"),
+ translate("ws.settings.wp.name.non.empty"));
+ return;
+ }
+ if (gc.existsWorkspace(wsName)){
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("i.am.sorry"),
+ translate("ws.settings.wp.exists.already"));
+ return;
+ }
+
+ // Make sure dir is an existing directory
+ if(!dir.exists()){
+ if (!dir.mkdirs()){
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("ws.error.title"),
+ translate("ws.settings.could.not.create.directory"));
+ return;
+ }
+ }else if (!dir.isDirectory()){
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("ws.error.title"),
+ translate("ws.settings.need.dir.not.file"));
+ return;
+ }
+ // dir exists & wsName doesn't exist yet => fine to create WS now
+ try {
+ WSManager.getInstance().createWorkspace(dir, wsName);
+ populateWorkspaceList();
+ } catch (IOException e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("ws.error.title"),
+ translate("ws.settings.could.not.create.ws"));
+ return;
+ }
+
+ }
+
+}
diff --git a/logo/src/xlogo/gui/welcome/settings/tabs/ContestTab.java b/logo/src/xlogo/gui/welcome/settings/tabs/ContestTab.java
new file mode 100644
index 0000000..e2dfa0a
--- /dev/null
+++ b/logo/src/xlogo/gui/welcome/settings/tabs/ContestTab.java
@@ -0,0 +1,197 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.welcome.settings.tabs;
+
+import java.awt.Dimension;
+
+import javax.swing.GroupLayout;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import xlogo.storage.WSManager;
+import xlogo.storage.workspace.WorkspaceConfig;
+
+public class ContestTab extends AbstractWorkspacePanel {
+
+ JPanel component;
+ JLabel workspaceLabel;
+ JComboBox workspaceSelection;
+ JLabel nOfFilesLabel;
+ JSpinner nOfFileSpinner;
+ JLabel nOfBonusFilesLabel;
+ JSpinner nOfBonusFileSpinner;
+
+ public JComponent getComponent()
+ {
+ return component;
+ }
+
+ @Override
+ protected JComboBox getWorkspaceSelection() {
+ return workspaceSelection;
+ }
+
+ @Override
+ protected void initComponent()
+ {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ component = new JPanel();
+
+ workspaceLabel = new JLabel();
+ workspaceSelection = new JComboBox();
+
+ nOfFilesLabel = new JLabel();
+ nOfFileSpinner = new JSpinner(new SpinnerNumberModel(wc.getNOfContestFiles(), 0, 100, 1));
+ JComponent editor = new JSpinner.NumberEditor(nOfFileSpinner);
+ nOfFileSpinner.setEditor(editor);
+
+ nOfBonusFilesLabel = new JLabel();
+ nOfBonusFileSpinner = new JSpinner(new SpinnerNumberModel(wc.getNOfContestBonusFiles(), 0, 100, 1));
+ JComponent editor2 = new JSpinner.NumberEditor(nOfBonusFileSpinner);
+ nOfBonusFileSpinner.setEditor(editor2);
+
+ populateWorkspaceList();
+ }
+
+ @Override
+ protected void layoutComponent()
+ {
+ workspaceSelection.setMinimumSize(new Dimension(150,25));
+ workspaceSelection.setMaximumSize(new Dimension(150,25));
+
+ nOfFileSpinner.setMinimumSize(new Dimension(25,25));
+ nOfFileSpinner.setMaximumSize(new Dimension(50,25));
+
+ nOfBonusFileSpinner.setMinimumSize(new Dimension(25,25));
+ nOfBonusFileSpinner.setMaximumSize(new Dimension(50,25));
+
+ component.add(workspaceLabel);
+ component.add(workspaceSelection);
+ component.add(nOfFilesLabel);
+ component.add(nOfFileSpinner);
+ component.add(nOfBonusFilesLabel);
+ component.add(nOfBonusFileSpinner);
+
+ GroupLayout groupLayout = new GroupLayout(component);
+ component.setLayout(groupLayout);
+
+ groupLayout.setAutoCreateGaps(true);
+ groupLayout.setAutoCreateContainerGaps(true);
+
+ groupLayout.setVerticalGroup(
+ groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspaceLabel)
+ .addComponent(workspaceSelection)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(nOfFilesLabel)
+ .addComponent(nOfFileSpinner)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(nOfBonusFilesLabel)
+ .addComponent(nOfBonusFileSpinner)
+ )
+ );
+
+ groupLayout.setHorizontalGroup(
+ groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspaceLabel)
+ .addComponent(nOfFilesLabel)
+ .addComponent(nOfBonusFilesLabel)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspaceSelection)
+ .addComponent(nOfFileSpinner)
+ .addComponent(nOfBonusFileSpinner)
+ )
+ );
+ }
+
+ @Override
+ protected void setText()
+ {
+ workspaceLabel.setText(translate("ws.settings.workspace"));
+ nOfFilesLabel.setText(translate("contest.number.of.files"));
+ nOfBonusFilesLabel.setText(translate("contest.number.of.bonus.files"));
+ }
+
+ @Override
+ protected void initEventListeners()
+ {
+ super.initEventListeners();
+
+ nOfFileSpinner.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent arg0) {
+ WSManager.getWorkspaceConfig().setNOfContestFiles((Integer) nOfFileSpinner.getValue());
+ }
+ });
+
+ nOfBonusFileSpinner.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ WSManager.getWorkspaceConfig().setNOfContestBonusFiles((Integer) nOfBonusFileSpinner.getValue());
+ }
+ });
+ }
+
+ @Override
+ public void stopEventListeners()
+ {
+ super.stopEventListeners();
+
+ }
+
+ @Override
+ protected void setValues() {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ nOfFileSpinner.setValue(wc.getNOfContestFiles());
+ nOfBonusFileSpinner.setValue(wc.getNOfContestBonusFiles());
+ }
+
+ @Override
+ protected void enableComponents() {
+ nOfFileSpinner.setEnabled(true);
+ nOfBonusFileSpinner.setEnabled(true);
+ }
+
+ @Override
+ protected void disableComponents() {
+ nOfFileSpinner.setEnabled(false);
+ nOfBonusFileSpinner.setEnabled(false);
+ }
+
+}
diff --git a/logo/src/xlogo/gui/welcome/settings/tabs/GlobalTab.java b/logo/src/xlogo/gui/welcome/settings/tabs/GlobalTab.java
new file mode 100644
index 0000000..ecaef9c
--- /dev/null
+++ b/logo/src/xlogo/gui/welcome/settings/tabs/GlobalTab.java
@@ -0,0 +1,230 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.welcome.settings.tabs;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.IOException;
+
+import javax.swing.GroupLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+
+import xlogo.gui.components.X4SComponent;
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.storage.WSManager;
+import xlogo.storage.global.GlobalConfig;
+/**
+ * @since June 10th 2014
+ * @author Marko
+ */
+public class GlobalTab extends X4SComponent {
+
+ private JPanel component;
+
+ private JCheckBox askPasswordCb;
+ private JLabel passwordLabel;
+ private JLabel retypeLabel;
+ private JPasswordField passwordField;
+ private JPasswordField retypeField;
+ private JButton save1;
+
+ private String authentification;
+
+ public GlobalTab() {
+ super();
+ }
+
+ public void authenticate(String authentification)
+ {
+ this.authentification = authentification;
+
+ boolean hasPw = authentification != null;
+ askPasswordCb.setSelected(hasPw);
+ showOrHidePw(hasPw);
+ passwordField.setText(authentification);
+ retypeField.setText(authentification);
+ }
+
+ public JComponent getComponent()
+ {
+ return component;
+ }
+
+ @Override
+ protected void initComponent()
+ {
+ component = new JPanel();
+
+ askPasswordCb = new JCheckBox("Protect these settings with a password.");
+ passwordLabel = new JLabel("Password");
+ retypeLabel = new JLabel("Retype Password");
+ passwordField = new JPasswordField();
+ retypeField = new JPasswordField();
+ save1 = new JButton("Save Password");
+ }
+
+ @Override
+ protected void layoutComponent()
+ {
+ passwordField.setMinimumSize(new Dimension(200, 25));
+ retypeField.setMinimumSize(new Dimension(200, 25));
+ passwordField.setMaximumSize(new Dimension(200, 25));
+ retypeField.setMaximumSize(new Dimension(200, 25));
+
+ component.add(askPasswordCb);
+ component.add(passwordLabel);
+ component.add(passwordField);
+ component.add(retypeLabel);
+ component.add(retypeField);
+ component.add(save1);
+
+ GroupLayout groupLayout = new GroupLayout(component);
+ component.setLayout(groupLayout);
+
+ groupLayout.setAutoCreateGaps(true);
+ groupLayout.setAutoCreateContainerGaps(true);
+
+ groupLayout.setVerticalGroup(
+ groupLayout.createSequentialGroup()
+ .addComponent(askPasswordCb)
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(passwordLabel)
+ .addComponent(passwordField))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(retypeLabel)
+ .addComponent(retypeField))
+ .addComponent(save1)
+ );
+
+ groupLayout.setHorizontalGroup(
+ groupLayout.createParallelGroup()
+ .addComponent(askPasswordCb)
+ .addGroup(groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(passwordLabel)
+ .addComponent(retypeLabel)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(passwordField)
+ .addComponent(retypeField)
+ )
+ )
+ .addComponent(save1)
+ );
+ }
+
+ @Override
+ protected void initEventListeners()
+ {
+ askPasswordCb.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ boolean selected = e.getStateChange() == ItemEvent.SELECTED;
+ showOrHidePw(selected);
+ passwordField.setText(null);
+ retypeField.setText(null);
+ if (!selected)
+ WSManager.getInstance().getGlobalConfigInstance().setNewPassword(authentification, null);
+ }
+ });
+
+ save1.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ try {
+ savePassword();
+ } catch (IOException e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("ws.error.title"),
+ translate("ws.settings.cannot.store.pw") + e.toString());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void stopEventListeners()
+ {
+ super.stopEventListeners();
+
+ }
+
+ private void showOrHidePw(boolean show)
+ {
+ askPasswordCb.setSelected(show);
+ passwordLabel.setVisible(show);
+ passwordField.setVisible(show);
+ retypeLabel.setVisible(show);
+ retypeField.setVisible(show);
+ save1.setVisible(show);
+ }
+
+ private void savePassword() throws IOException
+ {
+ GlobalConfig gc = WSManager.getInstance().getGlobalConfigInstance();
+
+ if (askPasswordCb.isSelected())
+ {
+ String pw1 = new String(passwordField.getPassword());
+ String pw2 = new String(retypeField.getPassword());
+ if (pw1.equals(pw2))
+ {
+ gc.setNewPassword(authentification, pw1);
+ authentification = pw1;
+ gc.store();
+ }
+ else
+ {
+ DialogMessenger.getInstance().dispatchMessage(
+ translate("i.am.sorry"),
+ translate("ws.settings.pw.must.be.equal"));
+ }
+ }else // checkbox not selected
+ {
+ gc.setNewPassword(authentification, null);
+ authentification = null;
+ gc.store();
+ }
+ }
+
+ @Override
+ protected void setText()
+ {
+ askPasswordCb.setText(translate("ws.settings.require_password"));
+ passwordLabel.setText(translate("ws.settings.password"));
+ retypeLabel.setText(translate("ws.settings.retype.password"));
+ save1.setText(translate("ws.settings.save.password"));
+ }
+
+}
diff --git a/logo/src/xlogo/gui/welcome/settings/tabs/SyntaxHighlightingTab.java b/logo/src/xlogo/gui/welcome/settings/tabs/SyntaxHighlightingTab.java
new file mode 100644
index 0000000..c5926f3
--- /dev/null
+++ b/logo/src/xlogo/gui/welcome/settings/tabs/SyntaxHighlightingTab.java
@@ -0,0 +1,288 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.welcome.settings.tabs;
+
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.GroupLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextPane;
+
+import xlogo.AppSettings;
+import xlogo.StyledDocument.DocumentLogo;
+import xlogo.gui.components.ColorStyleSelectionPanel;
+import xlogo.storage.WSManager;
+import xlogo.storage.workspace.SyntaxHighlightConfig;
+import xlogo.storage.workspace.WorkspaceConfig;
+
+public class SyntaxHighlightingTab extends AbstractWorkspacePanel{
+ private JPanel component;
+
+ private JLabel workspaceLabel;
+ private JComboBox workspaceSelection;
+ private ColorStyleSelectionPanel commentStyleSelection;
+ private ColorStyleSelectionPanel braceStyleSelection;
+ private ColorStyleSelectionPanel primitiveStyleSelection;
+ private ColorStyleSelectionPanel operandStyleSelection;
+ private JCheckBox activateHighlightingCheckBox;
+ private JLabel activateHighlightingLabel;
+ private JButton restoreDefaultsButton;
+ private DocumentLogo previewLogoDocument;
+ private JTextPane previewTextPane;
+
+ private ActionListener syntaxHighlightChangeListener;
+
+ public SyntaxHighlightingTab() {
+ super();
+ }
+
+ public JComponent getComponent()
+ {
+ return component;
+ }
+
+ protected void initComponent()
+ {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ //Font font = wc.getFont();
+ component = new JPanel();
+ workspaceLabel = new JLabel();
+ workspaceSelection = new JComboBox();
+ commentStyleSelection=new ColorStyleSelectionPanel(wc.getCommentColor(), wc.getCommentStyle(), translate("pref.highlight.comment"));
+ braceStyleSelection=new ColorStyleSelectionPanel(wc.getBraceColor(), wc.getBraceStyle(), translate("pref.highlight.parenthesis"));
+ primitiveStyleSelection=new ColorStyleSelectionPanel(wc.getPrimitiveColor(), wc.getPrimitiveStyle(), translate("pref.highlight.primitive"));
+ operandStyleSelection=new ColorStyleSelectionPanel(wc.getOperatorColor(), wc.getOperatorStyle(), translate("pref.highlight.operand"));
+
+ previewTextPane=new JTextPane();
+ activateHighlightingCheckBox = new JCheckBox();
+ activateHighlightingLabel=new JLabel();
+ restoreDefaultsButton=new JButton();
+
+ //activateHighlightingLabel.setFont(font);
+ //restoreDefaultsButton.setFont(font);
+ previewTextPane.setOpaque(true);
+ previewTextPane.setBackground(Color.white);
+ previewLogoDocument=new DocumentLogo();
+ previewTextPane.setDocument(previewLogoDocument);
+ previewLogoDocument.setColore_Parenthese(true);
+
+ populateWorkspaceList();
+ setValues();
+ }
+
+ protected void layoutComponent()
+ {
+ component.add(workspaceLabel);
+ component.add(workspaceSelection);
+ component.add(activateHighlightingCheckBox);
+ component.add(activateHighlightingLabel);
+ component.add(commentStyleSelection.getComponent());
+ component.add(primitiveStyleSelection.getComponent());
+ component.add(operandStyleSelection.getComponent());
+ component.add(braceStyleSelection.getComponent());
+ component.add(previewTextPane);
+ component.add(restoreDefaultsButton);
+
+ GroupLayout groupLayout = new GroupLayout(component);
+ component.setLayout(groupLayout);
+
+ groupLayout.setAutoCreateGaps(true);
+ groupLayout.setAutoCreateContainerGaps(true);
+
+ groupLayout.setVerticalGroup(
+ groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspaceLabel)
+ .addComponent(workspaceSelection))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(activateHighlightingLabel)
+ .addComponent(activateHighlightingCheckBox))
+ .addComponent(commentStyleSelection.getComponent())
+ .addComponent(primitiveStyleSelection.getComponent())
+ .addComponent(operandStyleSelection.getComponent())
+ .addComponent(braceStyleSelection.getComponent())
+ .addComponent(previewTextPane)
+ .addComponent(restoreDefaultsButton)
+ );
+ groupLayout.setHorizontalGroup(
+ groupLayout.createParallelGroup()
+ .addGroup(groupLayout.createSequentialGroup()
+ .addComponent(workspaceLabel)
+ .addComponent(workspaceSelection))
+ .addGroup(groupLayout.createSequentialGroup()
+ .addComponent(activateHighlightingLabel)
+ .addComponent(activateHighlightingCheckBox))
+ .addComponent(commentStyleSelection.getComponent())
+ .addComponent(primitiveStyleSelection.getComponent())
+ .addComponent(operandStyleSelection.getComponent())
+ .addComponent(braceStyleSelection.getComponent())
+ .addComponent(previewTextPane)
+ .addComponent(restoreDefaultsButton)
+ );
+ }
+
+ protected void setText()
+ {
+ workspaceLabel.setText(translate("ws.settings.workspace"));
+ previewTextPane.setText(translate("pref.highlight.example"));
+ commentStyleSelection.setTitle(translate("pref.highlight.comment"));
+ braceStyleSelection.setTitle(translate("pref.highlight.parenthesis"));
+ primitiveStyleSelection.setTitle(translate("pref.highlight.primitive"));
+ operandStyleSelection.setTitle(translate("pref.highlight.operand"));
+ activateHighlightingLabel.setText(translate("pref.highlight.enabled"));
+ restoreDefaultsButton.setText(translate("pref.highlight.init"));
+ previewTextPane.setText(translate("pref.highlight.example"));
+ }
+
+ @Override
+ protected void initEventListeners()
+ {
+ super.initEventListeners();
+ activateHighlightingCheckBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ WSManager.getWorkspaceConfig().setSyntaxHighlightingEnabled(activateHighlightingCheckBox.isSelected());
+ }
+ });
+ restoreDefaultsButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ SyntaxHighlightConfig syntaxStyles = new SyntaxHighlightConfig();
+ WSManager.getWorkspaceConfig().setSyntaxHighlightConfig(syntaxStyles);
+ setValues();
+ }
+ });
+ AppSettings.getInstance().addSyntaxHighlightStyleChangeListener(
+ syntaxHighlightChangeListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ updateSyntaxHighlightingPreview();
+ }
+ });
+
+ operandStyleSelection.addStyleChangeListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ wc.setOperandColor(operandStyleSelection.color());
+ wc.setOperandStyle(operandStyleSelection.style());
+ }
+ });
+
+ braceStyleSelection.addStyleChangeListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ wc.setBraceColor(braceStyleSelection.color());
+ wc.setBraceStyle(braceStyleSelection.style());
+ }
+ });
+
+ primitiveStyleSelection.addStyleChangeListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ wc.setPrimitiveColor(primitiveStyleSelection.color());
+ wc.setPrimitiveStyle(primitiveStyleSelection.style());
+ }
+ });
+
+ commentStyleSelection.addStyleChangeListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ wc.setCommentColor(commentStyleSelection.color());
+ wc.setCommentStyle(commentStyleSelection.style());
+ }
+ });
+ }
+
+ @Override
+ public void stopEventListeners()
+ {
+ super.stopEventListeners();
+ AppSettings.getInstance().removeSyntaxHighlightStyleChangeListener(syntaxHighlightChangeListener);
+
+ }
+
+ @Override
+ protected JComboBox getWorkspaceSelection() {
+ return workspaceSelection;
+ }
+
+ @Override
+ protected void setValues() {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ commentStyleSelection.setColorAndStyle(wc.getCommentColor(), wc.getCommentStyle());
+ braceStyleSelection.setColorAndStyle(wc.getBraceColor(), wc.getBraceStyle());
+ primitiveStyleSelection.setColorAndStyle(wc.getPrimitiveColor(), wc.getPrimitiveStyle());
+ operandStyleSelection.setColorAndStyle(wc.getOperatorColor(), wc.getOperatorStyle());
+
+ updateSyntaxHighlightingPreview();
+ }
+
+ protected void updateSyntaxHighlightingPreview()
+ {
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+
+ boolean isHighlightingEnabled = wc.isSyntaxHighlightingEnabled();
+ activateHighlightingCheckBox.setSelected(isHighlightingEnabled);
+ commentStyleSelection.setEnabled(isHighlightingEnabled);
+ primitiveStyleSelection.setEnabled(isHighlightingEnabled);
+ braceStyleSelection.setEnabled(isHighlightingEnabled);
+ operandStyleSelection.setEnabled(isHighlightingEnabled);
+ restoreDefaultsButton.setEnabled(isHighlightingEnabled);
+ previewLogoDocument.setColoration(isHighlightingEnabled);
+
+ previewLogoDocument.initStyles(
+ wc.getCommentColor(), wc.getCommentStyle(),
+ wc.getPrimitiveColor(), wc.getPrimitiveStyle(),
+ wc.getBraceColor(), wc.getBraceStyle(),
+ wc.getOperatorColor(), wc.getOperatorStyle());
+
+ previewTextPane.setText(translate("pref.highlight.example"));
+ }
+
+ @Override
+ protected void enableComponents() {
+
+ }
+
+ @Override
+ protected void disableComponents() {
+
+ }
+
+}
diff --git a/logo/src/xlogo/gui/welcome/settings/tabs/WorkspaceCreationPanel.java b/logo/src/xlogo/gui/welcome/settings/tabs/WorkspaceCreationPanel.java
new file mode 100644
index 0000000..06f8ad6
--- /dev/null
+++ b/logo/src/xlogo/gui/welcome/settings/tabs/WorkspaceCreationPanel.java
@@ -0,0 +1,144 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.welcome.settings.tabs;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.GroupLayout;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import xlogo.gui.components.X4SComponent;
+import xlogo.storage.WSManager;
+
+class WorkspaceCreationPanel extends X4SComponent
+{
+
+ private JPanel component;
+
+ public JLabel wsNameLabel;
+ public JLabel locationLabel;
+ public JTextField wsNameField;
+ public JTextField locationField;
+ public JButton openFilechooserBtn;
+
+ public JComponent getComponent()
+ {
+ return component;
+ }
+
+ @Override
+ protected void initComponent() {
+ component = new JPanel();
+
+ wsNameLabel = new JLabel("Workspace Name");
+ locationLabel = new JLabel("Location");
+ wsNameField = new JTextField();
+ locationField = new JTextField();
+ openFilechooserBtn = new JButton("Browse");
+
+ locationField.setText(WSManager.getInstance().getGlobalConfigInstance().getLocation().toString());
+ locationField.setEditable(false);
+ }
+
+ @Override
+ protected void layoutComponent() {
+ component.add(wsNameLabel);
+ component.add(locationLabel);
+ component.add(wsNameField);
+ component.add(locationField);
+ component.add(openFilechooserBtn);
+
+ locationField.setMinimumSize(new Dimension(250,15));
+
+ GroupLayout groupLayout = new GroupLayout(component);
+ component.setLayout(groupLayout);
+
+ groupLayout.setAutoCreateContainerGaps(true);
+ groupLayout.setAutoCreateGaps(true);
+
+ groupLayout.setVerticalGroup(groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(wsNameLabel)
+ .addComponent(wsNameField)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(locationLabel)
+ .addComponent(locationField)
+ .addComponent(openFilechooserBtn)
+ )
+ );
+
+ groupLayout.setHorizontalGroup(groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(wsNameLabel)
+ .addComponent(locationLabel)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(wsNameField)
+ .addGroup(groupLayout.createSequentialGroup()
+ .addComponent(locationField)
+ .addComponent(openFilechooserBtn))
+ )
+ );
+
+ }
+
+ @Override
+ protected void initEventListeners()
+ {
+ openFilechooserBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ File location = getUserSelectedDirectory();
+ if (location != null)
+ locationField.setText(location.toString());
+ }
+ });
+ }
+
+ @Override
+ public void stopEventListeners()
+ {
+ super.stopEventListeners();
+
+ }
+
+ @Override
+ protected void setText()
+ {
+ wsNameLabel.setText(translate("ws.creation.panel.name"));
+ locationLabel.setText(translate("ws.creation.panel.location"));
+ openFilechooserBtn.setText(translate("ws.creation.panel.browse"));
+ }
+} \ No newline at end of file
diff --git a/logo/src/xlogo/gui/welcome/settings/tabs/WorkspaceTab.java b/logo/src/xlogo/gui/welcome/settings/tabs/WorkspaceTab.java
new file mode 100644
index 0000000..3b0e8a4
--- /dev/null
+++ b/logo/src/xlogo/gui/welcome/settings/tabs/WorkspaceTab.java
@@ -0,0 +1,537 @@
+/* XLogo4Schools - A Logo Interpreter specialized for use in schools, based on XLogo by Lo�c Le Coq
+ * Copyright (C) 2013 Marko Zivkovic
+ *
+ * Contact Information: marko88zivkovic at gmail dot com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version. This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ *
+ * This Java source code belongs to XLogo4Schools, written by Marko Zivkovic
+ * during his Bachelor thesis at the computer science department of ETH Z�rich,
+ * in the year 2013 and/or during future work.
+ *
+ * It is a reengineered version of XLogo written by Lo�c Le Coq, published
+ * under the GPL License at http://xlogo.tuxfamily.org/
+ *
+ * Contents of this file were entirely written by Marko Zivkovic
+ */
+
+package xlogo.gui.welcome.settings.tabs;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.GroupLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import xlogo.Logo;
+import xlogo.messages.async.dialog.DialogMessenger;
+import xlogo.storage.Storable;
+import xlogo.storage.WSManager;
+import xlogo.storage.global.GlobalConfig;
+import xlogo.storage.workspace.Language;
+import xlogo.storage.workspace.NumberOfBackups;
+import xlogo.storage.workspace.WorkspaceConfig;
+
+public class WorkspaceTab extends AbstractWorkspacePanel{
+
+ JPanel component;
+
+ JLabel workspaceLabel;
+ JLabel wsLocationLabel;
+ JLabel wsLanguageLabel;
+ JLabel wsBackupLabel;
+ JLabel userLabel;
+
+ JButton addWorkspaceBtn;
+ JButton addUserBtn;
+
+ JButton removeWorkspaceBtn;
+ JButton removeUserBtn;
+
+ JButton importWorkspaceBtn;
+ JButton importUserBtn;
+
+ JComboBox workspaceSelection;
+ JComboBox userSelection;
+ JLabel wsLocation;
+ JFileChooser wsLocationChooser;
+ JComboBox languageSelection;
+ JComboBox nOfBackupsSelecteion;
+ JCheckBox userCreatable;
+
+ public WorkspaceTab() {
+ super();
+ }
+
+ @Override
+ public JComponent getComponent()
+ {
+ return component;
+ }
+
+ @Override
+ protected JComboBox getWorkspaceSelection() {
+ return workspaceSelection;
+ }
+
+ protected void initComponent()
+ {
+ component = new JPanel();
+
+ workspaceLabel = new JLabel("Workspace: ");
+ wsLocationLabel = new JLabel("Location: ");
+ wsLanguageLabel = new JLabel("Language: ");
+ wsBackupLabel = new JLabel("Number of Backups: ");
+ userLabel = new JLabel("User: ");
+
+ addWorkspaceBtn = new JButton("Add");
+ addUserBtn = new JButton("Add");
+
+ removeWorkspaceBtn = new JButton("Remove");
+ removeUserBtn = new JButton("Remove");
+
+ importWorkspaceBtn = new JButton("Import");
+ importUserBtn = new JButton("Import");
+
+ workspaceSelection = new JComboBox();
+ userSelection = new JComboBox();
+ wsLocation = new JLabel();
+ wsLocationChooser = new JFileChooser();
+ languageSelection = new JComboBox(Language.values());
+ nOfBackupsSelecteion = new JComboBox(NumberOfBackups.values());
+ userCreatable = new JCheckBox("Allow the users to create new user accounts?");
+
+ populateWorkspaceList();
+ setValues();
+ }
+
+ protected void layoutComponent()
+ {
+ workspaceSelection.setMinimumSize(new Dimension(150,25));
+ workspaceSelection.setMaximumSize(new Dimension(150,25));
+ userSelection.setMinimumSize(new Dimension(150,25));
+ userSelection.setMaximumSize(new Dimension(150,25));
+ languageSelection.setMinimumSize(new Dimension(150,25));
+ languageSelection.setMaximumSize(new Dimension(150,25));
+ nOfBackupsSelecteion.setMinimumSize(new Dimension(75,25));
+ nOfBackupsSelecteion.setMaximumSize(new Dimension(75,25));
+
+ component.add(workspaceLabel);
+ component.add(wsLocationLabel);
+ component.add(wsLanguageLabel);
+ component.add(wsBackupLabel);
+ component.add(userLabel);
+
+ component.add(addWorkspaceBtn);
+ component.add(addUserBtn);
+ component.add(removeWorkspaceBtn);
+ component.add(removeUserBtn);
+ component.add(importWorkspaceBtn);
+ component.add(importUserBtn);
+
+ component.add(workspaceSelection);
+ component.add(userSelection);
+ component.add(wsLocation);
+ component.add(languageSelection);
+ component.add(nOfBackupsSelecteion);
+
+ GroupLayout groupLayout = new GroupLayout(component);
+ component.setLayout(groupLayout);
+
+ groupLayout.setAutoCreateGaps(true);
+ groupLayout.setAutoCreateContainerGaps(true);
+
+ groupLayout.setVerticalGroup(
+ groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspaceLabel)
+ .addComponent(workspaceSelection)
+ .addComponent(addWorkspaceBtn)
+ .addComponent(removeWorkspaceBtn)
+ .addComponent(importWorkspaceBtn))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(wsLocationLabel)
+ .addComponent(wsLocation))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(userLabel)
+ .addComponent(userSelection)
+ .addComponent(addUserBtn)
+ .addComponent(removeUserBtn)
+ .addComponent(importUserBtn))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(wsLanguageLabel)
+ .addComponent(languageSelection))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(wsBackupLabel)
+ .addComponent(nOfBackupsSelecteion))
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(userCreatable))
+ );
+
+ groupLayout.setHorizontalGroup(
+ groupLayout.createParallelGroup()
+ .addGroup(groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspaceLabel)
+ .addComponent(userLabel)
+ .addComponent(wsLocationLabel)
+ .addComponent(wsLanguageLabel)
+ .addComponent(wsBackupLabel)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addGroup(groupLayout.createSequentialGroup()
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(workspaceSelection)
+ .addComponent(userSelection)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(addWorkspaceBtn)
+ .addComponent(addUserBtn)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(removeWorkspaceBtn)
+ .addComponent(removeUserBtn)
+ )
+ .addGroup(groupLayout.createParallelGroup()
+ .addComponent(importWorkspaceBtn)
+ .addComponent(importUserBtn)
+ )
+ )
+ .addComponent(wsLocation)
+ .addComponent(languageSelection)
+ .addComponent(nOfBackupsSelecteion)
+ )
+ )
+ .addComponent(userCreatable)
+ );
+ }
+
+ @Override
+ protected void initEventListeners()
+ {
+ /*
+ * WORKSPACE [SELECT in super class]; ADD; REMOVE; IMPORT
+ */
+ super.initEventListeners();
+
+ addWorkspaceBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ new Thread(new Runnable() {
+ public void run() {
+ addWorkspace();
+ }
+ }).run();
+ }
+ });
+
+ removeWorkspaceBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ new Thread(new Runnable() {
+ public void run() {
+ deleteWorkspace();
+ }
+ }).run();
+ }
+ });
+
+ importWorkspaceBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ new Thread(new Runnable() {
+ public void run() {
+ importWorkspace();
+ }
+ }).run();
+ }
+ });
+
+ /*
+ * USER ADD; REMOVE; IMPORT
+ */
+
+ addUserBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ new Thread(new Runnable() {
+ public void run() {
+ addUser();
+ }
+ }).run();
+ }
+ });
+
+ removeUserBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ new Thread(new Runnable() {
+ public void run() {
+ removeUser();
+ }
+ }).run();
+ }
+ });
+
+ importUserBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ new Thread(new Runnable() {
+ public void run() {
+ importUser();
+ }
+ }).run();
+ }
+ });
+
+ /*
+ * LANGUAGE
+ */
+
+ languageSelection.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ new Thread(new Runnable() {
+ public void run() {
+ Language lang = (Language) languageSelection.getSelectedItem();
+ changeLanguage(lang);
+ }
+ }).run();
+ }
+ });
+
+ /*
+ * BACKUP VERSIONS
+ */
+
+ nOfBackupsSelecteion.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ NumberOfBackups n = (NumberOfBackups) nOfBackupsSelecteion.getSelectedItem();
+ WSManager.getInstance().getWorkspaceConfigInstance().setNumberOfBackups(n);
+ }
+ });
+
+ /*
+ * USER CREATION
+ */
+
+ userCreatable.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent arg0) {
+ boolean isAllowed = userCreatable.isSelected();
+ WSManager.getInstance().getWorkspaceConfigInstance().setAllowUserCreation(isAllowed);
+ }
+ });
+ }
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * WORKSPACE : ADD, REMOVE, IMPORT
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ /**
+ * On creation or when a workspace is set, the input elements must be set according to the current workspace properties.
+ */
+ protected void setValues()
+ {
+ WorkspaceConfig wc = WSManager.getInstance().getWorkspaceConfigInstance();
+ GlobalConfig gc = WSManager.getInstance().getGlobalConfigInstance();
+
+ // location text
+ if (wc == null)
+ {
+ String wsName = (String) workspaceSelection.getSelectedItem();
+ wsLocation.setText(gc.getWorkspaceDirectory(wsName).toString());
+ wsLocationLabel.setText(Logo.messages.getString("ws.settings.damaged"));
+ disableComponents();
+ return;
+ }else if(wc.isVirtual())
+ wsLocation.setText(Logo.messages.getString("ws.settings.virtual.ws.not.stored"));
+ else
+ wsLocation.setText(wc.getLocation().toString());
+
+ // user list
+ populateUserList();
+
+ // Language
+ languageSelection.setSelectedItem(wc.getLanguage());
+ changeLanguage(wc.getLanguage());
+
+ // Backups
+ nOfBackupsSelecteion.setSelectedItem(wc.getNumberOfBackups());
+
+ // User Creation
+ userCreatable.setSelected(wc.isUserCreationAllowed());
+ }
+
+ /**
+ * Disable controls that depend on the workspace and that cannot be used with a virtual workspace
+ * or a workspace that could not be loaded
+ */
+ protected void disableComponents()
+ {
+ WorkspaceConfig wc = WSManager.getInstance().getWorkspaceConfigInstance();
+ removeWorkspaceBtn.setEnabled(wc == null);
+ userSelection.setEnabled(false);
+ addUserBtn.setEnabled(false);
+ removeUserBtn.setEnabled(false);
+ importUserBtn.setEnabled(false);
+ nOfBackupsSelecteion.setEnabled(false);
+ userCreatable.setEnabled(false);
+ }
+
+ @Override
+ /**
+ * Enable if Workspace is successfully entered and if it is not virtual.
+ */
+ protected void enableComponents()
+ {
+ removeWorkspaceBtn.setEnabled(true);
+ userSelection.setEnabled(true);
+ addUserBtn.setEnabled(true);
+ removeUserBtn.setEnabled(true);
+ importUserBtn.setEnabled(true);
+ nOfBackupsSelecteion.setEnabled(true);
+ userCreatable.setEnabled(true);
+ }
+
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * USER : ADD, REMOVE, IMPORT
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+ private void populateUserList()
+ {
+ WorkspaceConfig wc = WSManager.getInstance().getWorkspaceConfigInstance();
+ String[] users = wc.getUserList();
+ userSelection.setModel(new DefaultComboBoxModel(users));
+ String lastUser = wc.getLastActiveUser();
+ userSelection.setSelectedItem(lastUser);
+ }
+
+ private void addUser()
+ {
+ String username = getUserText(Logo.messages.getString("ws.settings.enter.user.name"), Logo.messages.getString("ws.settings.create.new.user"));
+
+ if ((username == null) || (username.length() == 0))
+ return;
+
+ if (WSManager.getInstance().getWorkspaceConfigInstance().existsUserLogically(username))
+ {
+ DialogMessenger.getInstance().dispatchMessage(
+ Logo.messages.getString("ws.error.title"),
+ Logo.messages.getString("ws.settings.user.exists.already"));
+ return;
+ }
+
+ WSManager.getInstance().createUser(username);
+ populateUserList();
+ }
+
+ private void removeUser()
+ {
+ WSManager wsManager = WSManager.getInstance();
+ WorkspaceConfig wc = wsManager.getWorkspaceConfigInstance();
+
+ String username = (String) userSelection.getSelectedItem();
+ if (username == null)
+ return;
+ String userDirectory = wc.getUserDirectroy(username).toString();
+ String message =
+ Logo.messages.getString("ws.settings.want.delete.dir.1")
+ + userDirectory
+ + Logo.messages.getString("ws.settings.want.delete.dir.1");
+
+ boolean ans = getUserYesOrNo(message, Logo.messages.getString("ws.settings.remove.user"));
+
+ WSManager.getInstance().deleteUser(username, ans);
+
+ populateUserList();
+ }
+
+ private void importUser()
+ {
+ File dir = getUserSelectedDirectory();
+ if (dir == null)
+ return;
+
+ if (!WSManager.isUserDirectory(dir))
+ {
+ DialogMessenger.getInstance().dispatchMessage(
+ Logo.messages.getString("i.am.sorry"),
+ dir.toString() + Logo.messages.getString("ws.settings.not.legal.user.dir"));
+ return;
+ }
+
+ String newName = dir.getName();
+ WorkspaceConfig wc = WSManager.getWorkspaceConfig();
+ if (dir.equals(wc.getUserDirectroy(newName)))
+ {
+ DialogMessenger.getInstance().dispatchMessage("This user was already in the list.");
+ return;
+ }
+
+ while (wc.existsUserLogically(newName) || !Storable.checkLegalName(newName))
+ {
+ String msg = wc.existsUserLogically(newName) ?
+ "The user name " + newName + " already exists. Please choose a new name."
+ : "The chosen name contains illegal characters. Please choose a new name.";
+
+ newName = getUserText(msg, "Name Conflict");
+ if (newName == null)
+ return;
+ }
+
+ try {
+ WSManager.getInstance().importUser(dir, newName);
+ } catch (Exception e) {
+ DialogMessenger.getInstance().dispatchMessage(
+ Logo.messages.getString("ws.error.title"),
+ Logo.messages.getString("ws.settings.could.not.import.user") + e.toString());
+ }
+ populateUserList();
+ }
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * START : LANGUAGE
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ private void changeLanguage(Language lang) {
+ WorkspaceConfig wc = WSManager.getInstance().getWorkspaceConfigInstance();
+
+ if (wc.getLanguage() != lang)
+ {
+ wc.setLanguage(lang);
+ }
+ }
+
+ protected void setText()
+ {
+ workspaceLabel.setText(Logo.messages.getString("ws.settings.workspace"));
+ wsLocationLabel.setText(Logo.messages.getString("ws.settings.location"));
+ wsLanguageLabel.setText(Logo.messages.getString("ws.settings.language"));
+ wsBackupLabel.setText(Logo.messages.getString("ws.settings.backups"));
+ userLabel.setText(Logo.messages.getString("ws.settings.user"));
+ addWorkspaceBtn.setText(Logo.messages.getString("ws.settings.add"));
+ addUserBtn.setText(Logo.messages.getString("ws.settings.add"));
+ removeWorkspaceBtn.setText(Logo.messages.getString("ws.settings.remove"));
+ removeUserBtn.setText(Logo.messages.getString("ws.settings.remove"));
+ importWorkspaceBtn.setText(Logo.messages.getString("ws.settings.import"));
+ importUserBtn.setText(Logo.messages.getString("ws.settings.import"));
+ userCreatable.setText(Logo.messages.getString("ws.settings.enable.user.account.creation"));
+ }
+}