diff options
author | Marko Živković <[email protected]> | 2014-06-11 10:10:33 +0000 |
---|---|---|
committer | Marko Živković <[email protected]> | 2014-06-11 10:10:33 +0000 |
commit | 1107aa0763e3d7554408c401d2a1dbed11a94c51 (patch) | |
tree | 7074264bc7b63f2ee5ee14a39458380fcce1904b /logo/src/xlogo/gui |
Add initial directories and files
git-svn-id: https://svn.code.sf.net/p/xlogo4schools/svn/trunk@1 3b0d7934-f7ef-4143-9606-b51f2e2281fd
Diffstat (limited to 'logo/src/xlogo/gui')
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 Binary files differnew file mode 100644 index 0000000..097c3bc --- /dev/null +++ b/logo/src/xlogo/gui/components/fileslist/11_alerts_and_states_error.png diff --git a/logo/src/xlogo/gui/components/fileslist/1_navigation_accept.png b/logo/src/xlogo/gui/components/fileslist/1_navigation_accept.png Binary files differnew file mode 100644 index 0000000..cf5fab3 --- /dev/null +++ b/logo/src/xlogo/gui/components/fileslist/1_navigation_accept.png diff --git a/logo/src/xlogo/gui/components/fileslist/5_content_discard.png b/logo/src/xlogo/gui/components/fileslist/5_content_discard.png Binary files differnew file mode 100644 index 0000000..cedb108 --- /dev/null +++ b/logo/src/xlogo/gui/components/fileslist/5_content_discard.png diff --git a/logo/src/xlogo/gui/components/fileslist/5_content_edit.png b/logo/src/xlogo/gui/components/fileslist/5_content_edit.png Binary files differnew file mode 100644 index 0000000..f09b2e4 --- /dev/null +++ b/logo/src/xlogo/gui/components/fileslist/5_content_edit.png diff --git a/logo/src/xlogo/gui/components/fileslist/5_content_remove.png b/logo/src/xlogo/gui/components/fileslist/5_content_remove.png Binary files differnew file mode 100644 index 0000000..9f4c3d6 --- /dev/null +++ b/logo/src/xlogo/gui/components/fileslist/5_content_remove.png 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 Binary files differnew file mode 100644 index 0000000..8892697 --- /dev/null +++ b/logo/src/xlogo/gui/components/fileslist/close_icon2.png diff --git a/logo/src/xlogo/gui/components/fileslist/new_content.png b/logo/src/xlogo/gui/components/fileslist/new_content.png Binary files differnew file mode 100644 index 0000000..884c9d2 --- /dev/null +++ b/logo/src/xlogo/gui/components/fileslist/new_content.png 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"));
+ }
+}
|