001 /* This file is part of the project "Hilbert II" - http://www.qedeq.org
002 *
003 * Copyright 2000-2013, Michael Meyling <mime@qedeq.org>.
004 *
005 * "Hilbert II" is free software; you can redistribute
006 * it and/or modify it under the terms of the GNU General Public
007 * License as published by the Free Software Foundation; either
008 * version 2 of the License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 */
015
016 package org.qedeq.gui.se.pane;
017
018 import java.awt.Color;
019 import java.awt.Container;
020 import java.awt.Font;
021 import java.awt.event.ActionEvent;
022 import java.awt.event.ActionListener;
023 import java.awt.event.ComponentAdapter;
024 import java.awt.event.ComponentEvent;
025 import java.awt.event.MouseAdapter;
026 import java.awt.event.MouseEvent;
027 import java.io.File;
028 import java.io.IOException;
029 import java.util.List;
030
031 import javax.swing.AbstractAction;
032 import javax.swing.JFrame;
033 import javax.swing.JMenu;
034 import javax.swing.JMenuBar;
035 import javax.swing.JMenuItem;
036 import javax.swing.JOptionPane;
037 import javax.swing.JScrollPane;
038 import javax.swing.JSplitPane;
039 import javax.swing.JViewport;
040 import javax.xml.parsers.ParserConfigurationException;
041
042 import org.qedeq.base.io.IoUtility;
043 import org.qedeq.base.io.ResourceLoaderUtility;
044 import org.qedeq.base.io.TextInput;
045 import org.qedeq.base.trace.Trace;
046 import org.qedeq.base.utility.StringUtility;
047 import org.qedeq.base.utility.YodaUtility;
048 import org.qedeq.gui.se.element.CPTextArea;
049 import org.qedeq.gui.se.util.GuiHelper;
050 import org.qedeq.kernel.bo.KernelContext;
051 import org.qedeq.kernel.bo.module.InternalKernelServices;
052 import org.qedeq.kernel.bo.module.ModuleLabels;
053 import org.qedeq.kernel.bo.parser.MathParser;
054 import org.qedeq.kernel.bo.parser.ParserException;
055 import org.qedeq.kernel.bo.parser.Term;
056 import org.qedeq.kernel.bo.service.Element2LatexImpl;
057 import org.qedeq.kernel.bo.service.Element2Utf8Impl;
058 import org.qedeq.kernel.se.base.list.Element;
059 import org.qedeq.kernel.se.common.SourceFileExceptionList;
060 import org.qedeq.kernel.xml.handler.parser.LoadXmlOperatorListUtility;
061 import org.qedeq.kernel.xml.parser.BasicParser;
062 import org.xml.sax.SAXException;
063
064
065 /**
066 * Transform formulas into QEDEQ syntax formulas.
067 *
068 * @author Michael Meyling
069 */
070 public class ParserPane extends JFrame {
071
072 /** This class. */
073 private static final Class CLASS = ParserPane.class;
074
075 /** Source to parse. */
076 private CPTextArea source = new CPTextArea(true);
077
078 /** Parse result. */
079 private CPTextArea resultField = new CPTextArea(false);
080
081 /** Error messages. */
082 private CPTextArea error = new CPTextArea(false);
083
084 /** Make source scrollable. */
085 private JScrollPane sourceScroller = new JScrollPane();
086
087 /** Split between source and result. */
088 private JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
089
090 /** Menu for copy and paste. */
091 private JMenuBar menu = new JMenuBar();
092
093 /** List of {@link org.qedeq.kernel.parser.Operator}s. */
094 private final List operators;
095
096 /** Error position within source file. */
097 private int errorPosition = -1;
098
099 /** Split between previous split and error pane. */
100 private JSplitPane globalPane;
101
102 /** File that contains operator definitions. */
103 private final File resourceFile;
104
105 /** Use this parser. */
106 private final MathParser parser;
107
108
109 public ParserPane(final String name, final MathParser parser, final String title,
110 final String resourceName, final String sample) throws SourceFileExceptionList {
111 // LATER mime 20080131: hard coded window, change to FormLayout
112 super(title);
113 this.parser = parser;
114 source.setText(sample);
115 final String resourceDirectoryName = "config";
116 try {
117 resourceFile = ResourceLoaderUtility.getResourceFile(
118 KernelContext.getInstance().getConfig().getBasisDirectory(), resourceDirectoryName,
119 resourceName).getCanonicalFile();
120 } catch (final IOException e) { // should not occur
121 throw new RuntimeException(e);
122 }
123 // LATER mime 20100906: change name and loading mechanism (don't use source directory for file!!!)
124 try {
125 operators = LoadXmlOperatorListUtility.getOperatorList(
126 (InternalKernelServices) YodaUtility.getFieldValue(KernelContext.getInstance(), "services"),
127 resourceFile);
128 } catch (NoSuchFieldException e) { // programming error
129 throw new RuntimeException(e);
130 }
131 setupView(name);
132 updateView();
133 }
134
135 /**
136 * Assembles the GUI components of the panel.
137 *
138 * @param name Name of transformation source.
139 */
140 private final void setupView(final String name) {
141 final Container pane = getContentPane();
142 source.setDragEnabled(true);
143 source.setFont(new Font("monospaced", Font.PLAIN, pane.getFont().getSize()));
144 source.setAutoscrolls(true);
145 source.setCaretPosition(0);
146 source.setEditable(true);
147 source.getCaret().setVisible(false);
148 source.setLineWrap(true);
149 source.setWrapStyleWord(true);
150 source.setFocusable(true);
151
152 resultField.setFont(new Font("monospaced", Font.PLAIN, pane.getFont().getSize()));
153 resultField.setAutoscrolls(true);
154 resultField.setCaretPosition(0);
155 resultField.setEditable(false);
156 resultField.getCaret().setVisible(false);
157 resultField.setFocusable(true);
158 final JMenuItem item = new JMenuItem("Show as Text");
159 item.addActionListener(new ActionListener() {
160 public void actionPerformed(final ActionEvent e) {
161 final String text = resultField.getText().trim();
162 if (text.length() == 0) {
163 return;
164 }
165 ModuleLabels labels = new ModuleLabels();
166 Element2LatexImpl converter = new Element2LatexImpl(labels);
167 Element2Utf8Impl textConverter = new Element2Utf8Impl(converter);
168 Element[] elements = null;
169 try {
170 elements = BasicParser.createElements(text);
171 } catch (final ParserConfigurationException e1) {
172 Trace.fatal(CLASS, "setupView$actionPerformed", "Parser configuration error",
173 e1);
174 return;
175 } catch (final SAXException e1) {
176 // ignore
177 return;
178 }
179 final StringBuffer result = new StringBuffer();
180 for (int i = 0; i < elements.length; i++) {
181 final String[] parsed = textConverter.getUtf8(elements[i], 120);
182 for (int j = 0; j < parsed.length; j++) {
183 result.append(parsed[j] + "\n");
184 }
185 result.append("\n");
186 }
187 final TextPaneWindow window = new TextPaneWindow("QEDEQ formulas as unicode text",
188 GuiHelper.readImageIcon("oil/" + QedeqGuiConfig.getInstance().getIconSize()
189 + "/apps/education-mathematics.png"), result.toString());
190 window.setVisible(true);
191 }
192 });
193 resultField.addMenuItem(item);
194
195 error.setFont(new Font("monospaced", Font.PLAIN, pane.getFont().getSize()));
196 error.setForeground(Color.RED);
197 error.setAutoscrolls(true);
198 error.setCaretPosition(0);
199 error.setEditable(false);
200 error.getCaret().setVisible(false);
201 error.setFocusable(true);
202 error.addMouseListener(new MouseAdapter() {
203 public void mouseClicked(final MouseEvent e) {
204 updateView();
205 }
206
207 });
208
209 final JViewport qedeqPort = sourceScroller.getViewport();
210 qedeqPort.add(source);
211
212 final JScrollPane resultScroller = new JScrollPane();
213 final JViewport resultPort = resultScroller.getViewport();
214 resultPort.add(resultField);
215
216 final JScrollPane errorScroller = new JScrollPane();
217 final JViewport errorPort = errorScroller.getViewport();
218 errorPort.add(error);
219
220 splitPane.setTopComponent(sourceScroller);
221 splitPane.setBottomComponent(resultScroller);
222 splitPane.setResizeWeight(0);
223 splitPane.setOneTouchExpandable(true);
224
225 error.setText("");
226
227 globalPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
228 globalPane.setTopComponent(splitPane);
229 globalPane.setBottomComponent(errorScroller);
230 globalPane.setResizeWeight(1);
231 globalPane.setOneTouchExpandable(true);
232
233 pane.add(globalPane);
234
235 addComponentListener(new ComponentAdapter() {
236 public void componentHidden(final ComponentEvent e) {
237 Trace.trace(CLASS, this, "componentHidden", e);
238 }
239 public void componentShown(final ComponentEvent e) {
240 Trace.trace(CLASS, this, "componentShown", e);
241 }
242 });
243
244 menu.removeAll();
245
246 /*
247 final JMenu fileMenu = new JMenu("File");
248 fileMenu.setMnemonic('F');
249 {
250 final JMenuItem transform = new JMenuItem("Load");
251 transform.setMnemonic('L');
252 transform.addActionListener(new AbstractAction() {
253 public final void actionPerformed(final ActionEvent action) {
254 }
255 });
256 fileMenu.add(transform);
257 }
258 menu.add(fileMenu);
259 setJMenuBar(menu);
260 */
261 final JMenu transformMenu = new JMenu("Transform");
262 transformMenu.setMnemonic('T');
263 {
264 final JMenuItem transform = new JMenuItem(name + " to QEDEQ");
265 transform.setMnemonic('Q');
266 transform.addActionListener(new AbstractAction() {
267 public final void actionPerformed(final ActionEvent action) {
268 resultField.setText(printMath(source.getText()));
269 updateView();
270 }
271 });
272 transformMenu.add(transform);
273 }
274 //** LATER mime 20071230: add conversion from QEDEQ into LaTeX
275 /*
276 {
277 final JMenuItem transform = new JMenuItem("QEDEQ to LaTeX");
278 transform.setMnemonic('L');
279 transform.addActionListener(new AbstractAction() {
280 public final void actionPerformed(final ActionEvent action) {
281 La
282 System.out.println(qedeq.getText());
283 result.setText(printMath(qedeq.getText()));
284 updateView();
285 }
286 });
287 transformMenu.add(transform);
288 }
289 */
290 {
291 final JMenuItem doSwitch = new JMenuItem("switch content");
292 doSwitch.setMnemonic('S');
293 doSwitch.addActionListener(new AbstractAction() {
294 public final void actionPerformed(final ActionEvent action) {
295 final String text = source.getText();
296 source.setText(resultField.getText());
297 resultField.setText(text);
298 updateView();
299 }
300 });
301 transformMenu.add(doSwitch);
302 }
303 menu.add(transformMenu);
304
305 final JMenu helpMenu = new JMenu("Help");
306 helpMenu.setMnemonic('H');
307 {
308 final JMenuItem about = new JMenuItem("About");
309 about.setMnemonic('A');
310 about.addActionListener(new AbstractAction() {
311 public final void actionPerformed(final ActionEvent action) {
312 JOptionPane.showMessageDialog(ParserPane.this,
313 "This dialog enables to transform textual input into the QEDEQ format.\n"
314 + "The operators and their QEDEQ counterparts are defined int the file:\n"
315 + resourceFile,
316 "About", JOptionPane.INFORMATION_MESSAGE);
317 }
318 });
319 helpMenu.add(about);
320 }
321 menu.add(helpMenu);
322
323 setJMenuBar(menu);
324 setSize(500, 800);
325 }
326
327 /**
328 * Set line wrap.
329 *
330 * @param wrap Line wrap?
331 */
332 public void setLineWrap(final boolean wrap) {
333 source.setLineWrap(wrap);
334 }
335
336 /**
337 * Get line wrap.
338 *
339 * @return Line wrap?
340 */
341 public boolean getLineWrap() {
342 return source.getLineWrap();
343 }
344
345 /**
346 * Update from model.
347 */
348 public synchronized void updateView() {
349 final String method = "updateView()";
350 Trace.begin(CLASS, this, method);
351
352 if (errorPosition >= 0) {
353 // reserve 3 text lines for error description
354 globalPane.setDividerLocation(globalPane.getHeight()
355 - globalPane.getDividerSize()
356 - error.getFontMetrics(error.getFont()).getHeight() * 3 - 4);
357 } else {
358 error.setText("");
359 globalPane.setDividerLocation(this.getHeight());
360 }
361 this.repaint();
362 }
363
364
365
366 // not used any longer
367 /*
368 private final int findCaretPosition(final int i) {
369 if (i == 1) {
370 return 0;
371 }
372 final String s = qedeq.getText();
373 int j = 0;
374 int k = 0;
375 for (; j < s.length(); j++) {
376 if (s.charAt(j) == '\n') {
377 k++;
378 }
379 if (k == i - 1) {
380 return j + 1;
381 }
382 }
383 return 0;
384 }
385 */
386
387 private String printMath(final String text) {
388 final StringBuffer buffer = new StringBuffer(text);
389 final TextInput input = new TextInput(buffer);
390 parser.setParameters(input, operators);
391 final StringBuffer out = new StringBuffer();
392 errorPosition = -1;
393 try {
394 Term term = null;
395 do {
396 term = parser.readTerm();
397 if (term != null) {
398 out.append(term.getQedeqXml()).append("\n");
399 System.out.println(term.getQedeqXml());
400 }
401 } while (term != null || !parser.eof());
402 } catch (ParserException e) {
403 e.printStackTrace(System.out);
404 final StringBuffer result = new StringBuffer();
405 errorPosition = input.getPosition();
406 result.append(input.getRow() + ":" + input.getColumn() + ":" + "\n");
407 result.append(e.getMessage() + "\n");
408 result.append(input.getLine().replace('\t', ' ').replace('\015', ' ') + "\n");
409 final StringBuffer pointer = StringUtility.getSpaces(input.getColumn());
410 pointer.append('^');
411 result.append(pointer);
412 System.out.println(result.toString());
413 error.setText(result.toString());
414 } catch (Exception e) {
415 e.printStackTrace(System.out);
416 final StringBuffer result = new StringBuffer();
417 errorPosition = input.getPosition();
418 result.append(input.getRow() + ":" + input.getColumn() + ":" + "\n");
419 result.append(e.getMessage() + "\n");
420 result.append(input.getLine().replace('\t', ' ').replace('\015', ' ') + "\n");
421 final StringBuffer pointer = StringUtility.getSpaces(input.getColumn());
422 pointer.append('^');
423 result.append(pointer);
424 System.out.println(result.toString());
425 error.setText(result.toString());
426 }
427 IoUtility.close(input); // to satisfy checkstyle
428 return out.toString();
429 }
430
431
432
433 }
|