improved the AllSolutionsDialog

This commit is contained in:
hneemann 2019-07-25 07:36:55 +02:00
parent e5266242d9
commit 51874037fb
5 changed files with 143 additions and 60 deletions

View File

@ -79,17 +79,13 @@ public final class GraphicsFormatter {
} else if (text instanceof Sentence) { } else if (text instanceof Sentence) {
Sentence s = (Sentence) text; Sentence s = (Sentence) text;
SentenceFragment sf = new SentenceFragment(); SentenceFragment sf = new SentenceFragment();
int x = 0;
for (Text t : s) for (Text t : s)
if (t instanceof Blank) if (t instanceof Blank)
x += font.getSize() / 2; sf.pad(font.getSize() / 2);
else { else {
final Fragment f = createFragment(sizer, font, t); final Fragment f = createFragment(sizer, font, t);
f.x = x;
x += f.dx;
sf.add(f); sf.add(f);
} }
sf.dx = x;
return sf.setUp(); return sf.setUp();
} else if (text instanceof Index) { } else if (text instanceof Index) {
Index i = (Index) text; Index i = (Index) text;
@ -154,27 +150,41 @@ public final class GraphicsFormatter {
NamedExpression ne = (NamedExpression) expression; NamedExpression ne = (NamedExpression) expression;
SentenceFragment f = new SentenceFragment(); SentenceFragment f = new SentenceFragment();
f.add(createFragment(sizer, font, ne.getName())); f.add(createFragment(sizer, font, ne.getName()));
f.pad(font.getSize()/2);
f.add(new TextFragment(sizer, font, "=")); f.add(new TextFragment(sizer, font, "="));
f.pad(font.getSize()/2);
f.add(createFragment(sizer, font, ne.getExpression())); f.add(createFragment(sizer, font, ne.getExpression()));
return f; return f.setUp();
} else } else
throw new FormatterException("unknown expression " + expression.getClass().getSimpleName()); throw new FormatterException("unknown expression " + expression.getClass().getSimpleName());
} }
private static Fragment createOperationFragment(FontSizer sizer, Font font, Operation op, String opString) throws FormatterException { private static Fragment createOperationFragment(FontSizer sizer, Font font, Operation op, String opString) throws FormatterException {
int pad = font.getSize() / 2;
SentenceFragment f = new SentenceFragment(); SentenceFragment f = new SentenceFragment();
for (Expression e : op.getExpressions()) { for (Expression e : op.getExpressions()) {
if (f.size() > 0) if (f.size() > 0) {
f.pad(pad);
if (!opString.isEmpty()) {
f.add(new TextFragment(sizer, font, opString)); f.add(new TextFragment(sizer, font, opString));
f.pad(pad);
}
}
if (e instanceof Operation) {
f.add(new TextFragment(sizer,font, "("));
f.add(createFragment(sizer, font, e));
f.add(new TextFragment(sizer,font, ")"));
} else {
f.add(createFragment(sizer, font, e)); f.add(createFragment(sizer, font, e));
} }
return f; }
return f.setUp();
} }
/** /**
* Exception which indicates a formatter exception * Exception which indicates a formatter exception
*/ */
private static final class FormatterException extends Exception { public static final class FormatterException extends Exception {
FormatterException(String message) { FormatterException(String message) {
super(message); super(message);
} }
@ -262,7 +272,7 @@ public final class GraphicsFormatter {
} }
} }
private final static class SentenceFragment extends Fragment { private static class SentenceFragment extends Fragment {
private ArrayList<Fragment> fragments; private ArrayList<Fragment> fragments;
@ -272,6 +282,12 @@ public final class GraphicsFormatter {
private void add(Fragment fragment) { private void add(Fragment fragment) {
fragments.add(fragment); fragments.add(fragment);
fragment.x = dx;
dx += fragment.dx;
}
private void pad(int p) {
dx += p;
} }
@Override @Override

View File

@ -83,7 +83,7 @@ public class TransitionTableCreator {
// create state variables // create state variables
ArrayList<Variable> vars = new ArrayList<>(); ArrayList<Variable> vars = new ArrayList<>();
for (int i = stateBits - 1; i >= 0; i--) { for (int i = stateBits - 1; i >= 0; i--) {
final Variable var = new Variable(STATE_VAR+"^" + i + "_n"); final Variable var = new Variable(STATE_VAR+"_" + i + "^n");
vars.add(var); vars.add(var);
boolean initVal = (initState & (1 << i)) != 0; boolean initVal = (initState & (1 << i)) != 0;
modelAnalyserInfo.setSequentialInitValue(var.getIdentifier(), initVal ? 1 : 0); modelAnalyserInfo.setSequentialInitValue(var.getIdentifier(), initVal ? 1 : 0);
@ -93,7 +93,7 @@ public class TransitionTableCreator {
// create the next state result variables // create the next state result variables
for (int i = stateBits - 1; i >= 0; i--) for (int i = stateBits - 1; i >= 0; i--)
truthTable.addResult(STATE_VAR+"^" + i + "_n+1"); truthTable.addResult(STATE_VAR+"_" + i + "^n+1");
// add the output variables // add the output variables
TreeSet<String> results = new TreeSet<>(); TreeSet<String> results = new TreeSet<>();

View File

@ -5,6 +5,7 @@
*/ */
package de.neemann.digital.gui.components.table; package de.neemann.digital.gui.components.table;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
import de.neemann.gui.Screen; import de.neemann.gui.Screen;
@ -12,13 +13,15 @@ import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.util.ArrayList;
import static de.neemann.digital.draw.graphics.text.formatter.GraphicsFormatter.createFragment;
/** /**
* Simple Dialog to show all possible functions of a truth table. * Simple Dialog to show all possible functions of a truth table.
*/ */
public class AllSolutionsDialog extends JDialog { public class AllSolutionsDialog extends JDialog {
private final JTextPane textPane; private final ExpressionComponent expressionComponent;
private final JScrollPane scroll;
private boolean userHasClosed = false; private boolean userHasClosed = false;
/** /**
@ -31,15 +34,11 @@ public class AllSolutionsDialog extends JDialog {
super(owner, Lang.get("win_allSolutions"), false); super(owner, Lang.get("win_allSolutions"), false);
setDefaultCloseOperation(HIDE_ON_CLOSE); setDefaultCloseOperation(HIDE_ON_CLOSE);
textPane = new JTextPane(); expressionComponent = new ExpressionComponent();
textPane.setContentType("text/html"); expressionComponent.setPreferredSize(Screen.getInstance().scale(new Dimension(600, 300)));
textPane.setFont(font); expressionComponent.setFont(font);
textPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true);
textPane.setEditable(false);
textPane.setPreferredSize(Screen.getInstance().scale(new Dimension(600, 300)));
scroll = new JScrollPane(textPane); getContentPane().add(new JScrollPane(expressionComponent));
getContentPane().add(scroll);
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
@Override @Override
@ -52,18 +51,6 @@ public class AllSolutionsDialog extends JDialog {
setLocation(0, 0); setLocation(0, 0);
} }
/**
* Sets the given text to the frame.
*
* @param text the text
* @return this for call chaining
*/
public AllSolutionsDialog setText(String text) {
textPane.setText(text);
SwingUtilities.invokeLater(() -> scroll.getViewport().setViewPosition(new Point(0, 0)));
return this;
}
/** /**
* Is called from table dialog if this dialog is needed. * Is called from table dialog if this dialog is needed.
* *
@ -73,4 +60,15 @@ public class AllSolutionsDialog extends JDialog {
if (!userHasClosed) if (!userHasClosed)
setVisible(needed); setVisible(needed);
} }
/**
* Sets the expressions
*
* @param expressions the expressions to show
*/
public void setExpressions(ArrayList<Expression> expressions) {
expressionComponent.setExpressions(expressions);
}
} }

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2019 Helmut Neemann.
* Use of this source code is governed by the GPL v3 license
* that can be found in the LICENSE file.
*/
package de.neemann.digital.gui.components.table;
import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.draw.graphics.text.formatter.GraphicsFormatter;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import static de.neemann.digital.draw.graphics.text.formatter.GraphicsFormatter.createFragment;
/**
* Component to show an expression
*/
public class ExpressionComponent extends JComponent {
private ArrayList<Expression> expressions;
private Dimension lastRectSet;
/**
* Sets the expressions to visualize
*
* @param expressions expressions
*/
public void setExpressions(ArrayList<Expression> expressions) {
this.expressions = expressions;
invalidate();
repaint();
}
@Override
protected void paintComponent(Graphics graphics) {
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, getWidth(), getHeight());
graphics.setColor(Color.BLACK);
if (expressions == null)
return;
final Graphics2D gr = (Graphics2D) graphics;
gr.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
gr.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
int lineSpacing = getFont().getSize() / 2;
int y = 0;
int dx = 0;
for (Expression e : expressions) {
try {
GraphicsFormatter.Fragment fr = createFragment(gr, e);
y += fr.getHeight();
fr.draw(gr, 5, y);
y += lineSpacing;
if (dx < fr.getWidth())
dx = fr.getWidth();
} catch (GraphicsFormatter.FormatterException ex) {
}
}
Dimension p = new Dimension(dx, y);
if (!p.equals(lastRectSet)) {
lastRectSet = p;
SwingUtilities.invokeLater(() -> {
setPreferredSize(p);
invalidate();
});
}
}
}

View File

@ -11,6 +11,7 @@ import de.neemann.digital.analyse.TruthTable;
import de.neemann.digital.analyse.TruthTableTableModel; import de.neemann.digital.analyse.TruthTableTableModel;
import de.neemann.digital.analyse.expression.Expression; import de.neemann.digital.analyse.expression.Expression;
import de.neemann.digital.analyse.expression.ExpressionException; import de.neemann.digital.analyse.expression.ExpressionException;
import de.neemann.digital.analyse.expression.NamedExpression;
import de.neemann.digital.analyse.expression.Variable; import de.neemann.digital.analyse.expression.Variable;
import de.neemann.digital.analyse.expression.format.FormatToExpression; import de.neemann.digital.analyse.expression.format.FormatToExpression;
import de.neemann.digital.analyse.expression.format.FormatToTableLatex; import de.neemann.digital.analyse.expression.format.FormatToTableLatex;
@ -606,7 +607,7 @@ public class TableDialog extends JDialog {
private void calculateExpressions() { private void calculateExpressions() {
try { try {
LOGGER.info("start optimization"); LOGGER.info("start optimization");
ExpressionListener expressionListener = new HTMLExpressionListener(); ExpressionListener expressionListener = new OutputExpressionListener();
if (createJK.isSelected()) if (createJK.isSelected())
expressionListener = new ExpressionListenerJK(expressionListener); expressionListener = new ExpressionListenerJK(expressionListener);
@ -688,7 +689,7 @@ public class TableDialog extends JDialog {
public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) {
ArrayList<Variable> vars = new ArrayList<>(); ArrayList<Variable> vars = new ArrayList<>();
for (int i = n - 1; i >= 0; i--) for (int i = n - 1; i >= 0; i--)
vars.add(new Variable("Q_" + i + "n")); vars.add(new Variable("Q" + i + "n"));
TruthTable truthTable = new TruthTable(vars); TruthTable truthTable = new TruthTable(vars);
int i = n - 1; int i = n - 1;
int rows = 1 << n; int rows = 1 << n;
@ -717,7 +718,7 @@ public class TableDialog extends JDialog {
ArrayList<Variable> vars = new ArrayList<>(); ArrayList<Variable> vars = new ArrayList<>();
vars.add(new Variable("dir")); vars.add(new Variable("dir"));
for (int i = n - 1; i >= 0; i--) for (int i = n - 1; i >= 0; i--)
vars.add(new Variable("Q_" + i + "n")); vars.add(new Variable("Q" + i + "n"));
TruthTable truthTable = new TruthTable(vars); TruthTable truthTable = new TruthTable(vars);
int i = n - 1; int i = n - 1;
int rows = 1 << (n + 1); int rows = 1 << (n + 1);
@ -759,47 +760,42 @@ public class TableDialog extends JDialog {
} }
} }
private final class HTMLExpressionListener implements ExpressionListener { private final class OutputExpressionListener implements ExpressionListener {
private FormatToExpression htmlFormatter = new HTMLFormatter(FormatToExpression.getDefaultFormat()); private FormatToExpression htmlFormatter = new HTMLFormatter(FormatToExpression.getDefaultFormat());
private final StringBuilder html; private final ArrayList<Expression> expressions;
private int count;
private String firstExp;
private HTMLExpressionListener() { private OutputExpressionListener() {
html = new StringBuilder("<html><table style=\"white-space: nowrap\">\n"); expressions = new ArrayList<>();
count = 0;
} }
@Override @Override
public void resultFound(String name, Expression expression) throws FormatterException { public void resultFound(String name, Expression expression) {
if (count == 0) if (name.endsWith("^n+1"))
firstExp = "<html>" + htmlFormatter.identifier(name) + "=" + htmlFormatter.format(expression) + "</html>"; name = name.substring(0, name.length() - 4) + "^{n+1}";
html.append("<tr>"); expressions.add(new NamedExpression(name, expression));
html.append("<td>").append(htmlFormatter.identifier(name)).append("</td>");
html.append("<td>=</td>");
html.append("<td>").append(htmlFormatter.format(expression)).append("</td>");
html.append("</tr>\n");
count++;
} }
@Override @Override
public void close() { public void close() throws FormatterException {
html.append("</table></html>"); String html = null;
if (expressions.size() == 1)
html = "<html>" + htmlFormatter.format(expressions.get(0)) + "</html>";
final String finalHtml = html;
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
switch (count) { switch (expressions.size()) {
case 0: case 0:
statusBar.setVisible(false); statusBar.setVisible(false);
allSolutionsDialog.setNeeded(false); allSolutionsDialog.setNeeded(false);
break; break;
case 1: case 1:
statusBar.setVisible(true); statusBar.setVisible(true);
statusBar.setText(firstExp); statusBar.setText(finalHtml);
allSolutionsDialog.setNeeded(false); allSolutionsDialog.setNeeded(false);
break; break;
default: default:
statusBar.setVisible(false); statusBar.setVisible(false);
allSolutionsDialog.setText(html.toString()); allSolutionsDialog.setExpressions(expressions);
allSolutionsDialog.setNeeded(true); allSolutionsDialog.setNeeded(true);
} }
}); });