use of javax.swing.text.html.HTMLEditorKit in project freeplane by freeplane.
the class MTextController method getContent.
private String[] getContent(final String text, final int pos) {
if (pos <= 0) {
return null;
}
final String[] strings = new String[2];
if (text.startsWith("<html>")) {
final HTMLEditorKit kit = new HTMLEditorKit();
final HTMLDocument doc = new HTMLDocument();
final StringReader buf = new StringReader(text);
try {
kit.read(buf, doc, 0);
final char[] firstText = doc.getText(0, pos).toCharArray();
int firstStart = 0;
int firstLen = pos;
while ((firstStart < firstLen) && (firstText[firstStart] <= ' ')) {
firstStart++;
}
while ((firstStart < firstLen) && (firstText[firstLen - 1] <= ' ')) {
firstLen--;
}
int secondStart = 0;
int secondLen = doc.getLength() - pos;
if (secondLen <= 0)
return null;
final char[] secondText = doc.getText(pos, secondLen).toCharArray();
while ((secondStart < secondLen) && (secondText[secondStart] <= ' ')) {
secondStart++;
}
while ((secondStart < secondLen) && (secondText[secondLen - 1] <= ' ')) {
secondLen--;
}
if (firstStart == firstLen || secondStart == secondLen) {
return null;
}
StringWriter out = new StringWriter();
new FixedHTMLWriter(out, doc, firstStart, firstLen - firstStart).write();
strings[0] = out.toString();
out = new StringWriter();
new FixedHTMLWriter(out, doc, pos + secondStart, secondLen - secondStart).write();
strings[1] = out.toString();
return strings;
} catch (final IOException e) {
LogUtils.severe(e);
} catch (final BadLocationException e) {
LogUtils.severe(e);
}
} else {
if (pos >= text.length()) {
return null;
}
strings[0] = text.substring(0, pos);
strings[1] = text.substring(pos);
}
return strings;
}
use of javax.swing.text.html.HTMLEditorKit in project semiprime by entangledloops.
the class ClientGui method create.
/**
* Generates a new window for the app that provides a gui to manage a local
* search or contribute to an ongoing server-based search.
*
* @return true if everything went okay, false otherwise
*/
private boolean create() {
// the preferences object that will hold all user settings
prefs = Preferences.userNodeForPackage(getClass());
try {
final boolean jar = Utils.jar();
icnNodeSmall = jar ? new ImageIcon(ImageIO.read(Utils.getResourceFromJar(ICON_NODE_SMALL))) : new ImageIcon(Utils.getResource(ICON_NODE_SMALL));
icnNodeMedium = jar ? new ImageIcon(ImageIO.read(Utils.getResourceFromJar(ICON_NODE_MEDIUM))) : new ImageIcon(Utils.getResource(ICON_NODE_MEDIUM));
icnNode = jar ? new ImageIcon(ImageIO.read(Utils.getResourceFromJar(ICON_NODE))) : new ImageIcon(Utils.getResource(ICON_NODE));
icnCpu = jar ? new ImageIcon(ImageIO.read(Utils.getResourceFromJar(ICON_CPU))) : new ImageIcon(Utils.getResource(ICON_CPU));
icnNetMedium = jar ? new ImageIcon(ImageIO.read(Utils.getResourceFromJar(ICON_NET_MEDIUM))) : new ImageIcon(Utils.getResource(ICON_NET_MEDIUM));
icnNet = jar ? new ImageIcon(ImageIO.read(Utils.getResourceFromJar(ICON_NET))) : new ImageIcon(Utils.getResource(ICON_NET));
icnMisc = jar ? new ImageIcon(ImageIO.read(Utils.getResourceFromJar(ICON_SETTINGS))) : new ImageIcon(Utils.getResource(ICON_SETTINGS));
setIconImage(icnNode.getImage());
} catch (Throwable t) {
Log.e(t);
}
// //////////////////////////////////////////////////////////////////////////
// menus
final JMenuBar mnuBar = new JMenuBar();
// /////////////////////////////
final JMenu mnuFile = new JMenu("File");
mnuBar.add(mnuFile);
final JMenuItem mnuSaveSettings = new JMenuItem("Save Settings");
mnuSaveSettings.addActionListener(l -> saveSettings());
mnuFile.add(mnuSaveSettings);
final JMenuItem mnuLoadSettings = new JMenuItem("Load Settings");
mnuLoadSettings.addActionListener(l -> loadSettings());
mnuFile.add(mnuLoadSettings);
// /////////////////////////////
mnuFile.addSeparator();
final JMenuItem mnuSendWork = new JMenuItem("Send Completed Work Now");
mnuSendWork.addActionListener(l -> sendWork());
mnuFile.add(mnuSendWork);
final JMenuItem mnuRecvWork = new JMenuItem("Request New Search Root");
mnuRecvWork.addActionListener(l -> recvWork());
mnuFile.add(mnuRecvWork);
// /////////////////////////////
mnuFile.addSeparator();
final JMenuItem mnuQuit = new JMenuItem("Quit Discarding Changes");
mnuQuit.addActionListener(l -> exit(false));
mnuFile.add(mnuQuit);
final JMenuItem mnuSaveAndQuit = new JMenuItem("Save & Quit");
mnuSaveAndQuit.addActionListener(l -> exit());
mnuFile.add(mnuSaveAndQuit);
try {
final JMenu mnuAbout = new JMenu("About");
final URI aboutURI = new URI(ABOUT_URL);
final JMenuItem mnuSPF = new JMenuItem("What is Semiprime Factorization?");
mnuSPF.addActionListener(l -> {
try {
java.awt.Desktop.getDesktop().browse(aboutURI);
} catch (Throwable t) {
Log.e(t);
}
});
mnuAbout.add(mnuSPF);
final URI noMathURI = new URI(NO_MATH_URL);
final JMenuItem mnuNoMath = new JMenuItem("Explain it again, but like I don't know any math.");
mnuNoMath.addActionListener(l -> {
try {
java.awt.Desktop.getDesktop().browse(noMathURI);
} catch (Throwable t) {
Log.e(t);
}
});
mnuAbout.add(mnuNoMath);
// /////////////////////////////
mnuAbout.addSeparator();
final URI downloadURI = new URI(SOURCE_URL);
final JMenuItem mnuDownload = new JMenuItem("Download Latest Client");
mnuDownload.addActionListener(l -> {
try {
java.awt.Desktop.getDesktop().browse(downloadURI);
} catch (Throwable t) {
Log.e(t);
}
});
mnuAbout.add(mnuDownload);
final URI sourceURI = new URI(SOURCE_URL);
final JMenuItem mnuSource = new JMenuItem("Source Code");
mnuSource.addActionListener(l -> {
try {
java.awt.Desktop.getDesktop().browse(sourceURI);
} catch (Throwable t) {
Log.e(t);
}
});
mnuAbout.add(mnuSource);
// /////////////////////////////
mnuAbout.addSeparator();
final URI homepageURI = new URI(HOMEPAGE_URL);
final JMenuItem mnuHomepage = new JMenuItem("My Homepage");
mnuHomepage.addActionListener(l -> {
try {
java.awt.Desktop.getDesktop().browse(homepageURI);
} catch (Throwable t) {
Log.e(t);
}
});
mnuAbout.add(mnuHomepage);
mnuBar.add(mnuAbout);
} catch (Throwable t) {
Log.o("for more info, visit:\n" + ABOUT_URL);
Log.e(t);
}
setJMenuBar(mnuBar);
// //////////////////////////////////////////////////////////////////////////
// connect tab
// gather basic info about this device
final double toGb = 1024.0 * 1024.0 * 1024.0;
final Runtime runtime = Runtime.getRuntime();
final String version = Runtime.class.getPackage().getImplementationVersion();
final int processors = runtime.availableProcessors();
// initialize all components to default settings
// JTextArea();
txtLog = new JTextPane();
txtLog.setContentType("text/html");
// txtLog.setRows(DEFAULT_HISTORY_ROWS);
// txtLog.setColumns(DEFAULT_HISTORY_COLS);
// txtLog.setLineWrap(true);
// /txtLog.setWrapStyleWord(true);
txtLog.setEditable(false);
txtLog.setVisible(true);
txtLog.setEnabled(true);
Log.init(s -> {
final Runnable append = () -> {
HTMLDocument document = (HTMLDocument) txtLog.getDocument();
HTMLEditorKit editorKit = (HTMLEditorKit) txtLog.getEditorKit();
try {
editorKit.insertHTML(document, document.getLength(), html(s) + "<br>", 0, 0, null);
} catch (Throwable ignored) {
}
final int pos = document.getLength();
txtLog.setCaretPosition(pos < 0 ? 0 : pos);
};
try {
if (SwingUtilities.isEventDispatchThread())
SwingUtilities.invokeLater(append);
else
append.run();
}// don't care what went wrong with gui update, it's been logged anyway
catch (Throwable ignored) {
}
});
final JScrollPane pneHistory = new JScrollPane(txtLog);
txtLog.setHighlighter(new DefaultHighlighter());
pneHistory.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
pneHistory.setVisible(true);
// username
final JLabel lblUsername = getLabel("Optional username:");
txtUsername = getTextField(DEFAULT_USERNAME);
// email
final JLabel lblEmail = getLabel("Optional email (in case you crack a number\u2014will never share):");
txtEmail = getTextField(DEFAULT_EMAIL);
// host address label and text box
final JLabel lblAddress = getLabel("Server address:");
txtHost = getTextField(DEFAULT_HOST);
txtHost.setColumns(DEFAULT_HOST.length());
// port box and restrict to numbers
final JLabel lblPort = getLabel("Server port:");
txtPort = getNumberTextField("" + DEFAULT_PORT);
txtPort.setColumns(5);
final JLabel lblConnectNow = getLabel("Click update if you change your username or email after connecting:");
btnConnect = getButton("Connect Now");
btnConnect.setIcon(icnNetMedium);
btnConnect.addActionListener(e -> {
if (isConnecting.compareAndSet(false, true))
connect();
});
btnUpdate = getButton("Update");
btnUpdate.setEnabled(false);
btnUpdate.addActionListener(e -> sendSettings());
final JPanel pnlConnectBtn = new JPanel(new GridLayout(1, 2));
pnlConnectBtn.add(btnConnect);
pnlConnectBtn.add(btnUpdate);
// add the components to the left-side connect region
final JPanel pnlConnect = new JPanel(new GridLayout(10, 1));
pnlConnect.add(lblUsername);
pnlConnect.add(txtUsername);
pnlConnect.add(lblEmail);
pnlConnect.add(txtEmail);
pnlConnect.add(lblAddress);
pnlConnect.add(txtHost);
pnlConnect.add(lblPort);
pnlConnect.add(txtPort);
pnlConnect.add(lblConnectNow);
pnlConnect.add(pnlConnectBtn);
// organize them and add them to the panel
final JPanel pnlNet = new JPanel(new GridLayout(2, 1));
pnlNet.add(pneHistory);
pnlNet.add(pnlConnect);
// //////////////////////////////////////////////////////////////////////////
// search tab
chkFavorPerformance = getCheckBox(FAVOR_PERFORMANCE_NAME, DEFAULT_FAVOR_PERFORMANCE);
chkFavorPerformance.setToolTipText("<html>CPU performance will be favored, but (possibly lots) more memory will be consumed.<br>Watch caching if you have a solid state drive.</html>");
chkFavorPerformance.addActionListener((e) -> Solver.favorPerformance(chkFavorPerformance.isSelected()));
chkCompressMemory = getCheckBox(COMPRESS_MEMORY_NAME, DEFAULT_COMPRESS_MEMORY);
chkCompressMemory.setToolTipText("Memory will be spared, but possibly at great cost to CPU time.");
chkCompressMemory.addActionListener((e) -> Solver.compressMemory(chkCompressMemory.isSelected()));
chkRestrictDisk = getCheckBox(RESTRICT_DISK_NAME, DEFAULT_RESTRICT_DISK);
chkRestrictDisk.setToolTipText("Disk I/O enabled or disabled for caching search if/when memory runs low.");
chkRestrictDisk.addActionListener((e) -> Solver.restrictDisk(chkRestrictDisk.isSelected()));
// ///////////////////////////////////
chkRestrictNetwork = getCheckBox(RESTRICT_NETWORK_NAME, DEFAULT_RESTRICT_NETWORK);
chkRestrictNetwork.setToolTipText("Memory will be spared, but possibly at great cost to CPU time.");
chkRestrictNetwork.addActionListener((e) -> Solver.restrictNetwork(chkRestrictNetwork.isSelected()));
chkPeriodicStats = getCheckBox(PERIODIC_STATS_NAME, DEFAULT_PERIODIC_STATS);
chkPeriodicStats.setToolTipText("Print stats reflecting search status every so often.");
chkPeriodicStats.addActionListener((e) -> Solver.stats(chkPeriodicStats.isSelected()));
chkDetailedStats = getCheckBox(DETAILED_STATS_NAME, DEFAULT_DETAILED_STATS);
chkDetailedStats.setToolTipText("Calculated detailed stats at great performance and memory cost (use to debug).");
chkDetailedStats.addActionListener((e) -> Solver.detailedStats(chkDetailedStats.isSelected()));
// ///////////////////////////////////
chkPrintAllNodes = getCheckBox(PRINT_ALL_NODES_NAME, DEFAULT_PRINT_ALL_NODES);
chkPrintAllNodes.setToolTipText("<html>All nodes generated and expanded will be printed in the order of occurrence.<br>This will bring search speed to a halt and eat tons of memory for large search spaces!</html>");
chkPrintAllNodes.addActionListener((e) -> Solver.printAllNodes(chkPrintAllNodes.isSelected()));
chkWriteCsv = getCheckBox(WRITE_CSV_NAME, DEFAULT_WRITE_CSV);
chkWriteCsv.setToolTipText("<html>All nodes generated will be written to disk in CSV format in order of occurrence.<br>This may bring search speed to a halt and/or fill your disk!</html>");
chkWriteCsv.addActionListener((e) -> {
try {
Solver.csv(chkWriteCsv.isSelected() ? new PrintWriter("search-results.csv") : null);
} catch (Throwable t) {
Log.e(t);
}
});
chkBackground = getCheckBox("work in background", prefs.getBoolean(BACKGROUND_NAME, DEFAULT_BACKGROUND));
chkBackground.setToolTipText("Only run when system is idle.");
chkBackground.addActionListener(l -> {
Solver.background(chkBackground.isSelected());
Log.o("background: " + (Solver.background() ? "yes" : "no"));
});
// ///////////////////////////////////
chkHeuristics = new JCheckBox[Heuristic.values().length];
for (int i = 0; i < Heuristic.values().length; ++i) {
chkHeuristics[i] = getCheckBox(Heuristic.values()[i].toString(), false);
chkHeuristics[i].setToolTipText(Heuristic.values()[i].description());
}
// ///////////////////////////////////
final JButton btnPause = getButton("Pause");
btnPause.setEnabled(false);
final JButton btnResume = getButton("Resume");
btnResume.setEnabled(false);
btnPause.addActionListener((e) -> {
btnPause.setEnabled(false);
solver().pause();
btnResume.setEnabled(true);
});
btnResume.addActionListener((e) -> {
btnResume.setEnabled(false);
solver().resume();
btnPause.setEnabled(true);
});
// ///////////////////////////////////
final Runnable semiprimeFormatter = () -> {
// grab the inputted target value and strip formatting
final String s = clean(txtSemiprime.getText()).toLowerCase();
// the assumptions made here regarding base are just to help speed up selecting settings,
// they are by *no means* meant to account for all "base-cases", which wouldn't be possible
// to do correctly in all cases w/o user-input anyway
boolean allBinaryDigits = true, containsHex = false, whitespaceChange = true;
for (char c : s.toCharArray()) {
if (Character.isWhitespace(c))
continue;
else
whitespaceChange = false;
if ('a' == c || 'b' == c || 'c' == c || 'd' == c || 'e' == c || 'f' == c) {
containsHex = true;
break;
} else if (c != '0' && c != '1') {
allBinaryDigits = false;
}
}
// if the change wasn't trivial...
if (!whitespaceChange) {
// try to guess the base
final String prevBase = clean(txtSemiprimeBase.getText());
if (containsHex)
txtSemiprimeBase.setText("16");
else if (allBinaryDigits)
txtSemiprimeBase.setText("2");
else
txtSemiprimeBase.setText("" + DEFAULT_SEMIPRIME_BASE);
// further ensure value change and clear old prime lengths
if (!prevBase.equals(clean(txtSemiprimeBase.getText()))) {
txtP1Len.setText("0");
txtP2Len.setText("0");
}
updateSemiprimeInfo();
}
};
txtSemiprime = new JTextArea(DEFAULT_HISTORY_ROWS, DEFAULT_HISTORY_COLS);
txtSemiprime.setHighlighter(new DefaultHighlighter());
txtSemiprime.addInputMethodListener(new InputMethodListener() {
@Override
public void inputMethodTextChanged(InputMethodEvent event) {
semiprimeFormatter.run();
}
@Override
public void caretPositionChanged(InputMethodEvent event) {
semiprimeFormatter.run();
}
});
txtSemiprime.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
semiprimeFormatter.run();
}
@Override
public void keyPressed(KeyEvent e) {
semiprimeFormatter.run();
}
@Override
public void keyReleased(KeyEvent e) {
semiprimeFormatter.run();
}
});
final JScrollPane pneSemiprime = new JScrollPane(txtSemiprime);
pneSemiprime.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
pneSemiprime.setVisible(true);
// ///////////////////////////////////
final String semiprimeBaseHelp = "The base that you are providing your semiprime in.";
final String internalBaseHelp = "The base that will be used internally by the solver.";
final String primeLengthHelp = "Measured in digits of internal base.\nUse 0 if unknown.";
final JLabel lblSemiprimeBase = getLabel("Semiprime Base");
lblSemiprimeBase.setToolTipText(semiprimeBaseHelp);
final JLabel lblInternalBase = getLabel("Internal Base");
lblInternalBase.setToolTipText(internalBaseHelp);
txtSemiprimeBase = getNumberTextField("10");
txtSemiprimeBase.setToolTipText(semiprimeBaseHelp);
txtInternalBase = getNumberTextField("2");
txtInternalBase.setEnabled(false);
txtInternalBase.setToolTipText(internalBaseHelp);
final JLabel lblP1Len = getLabel("Prime 1 (p) Length");
lblP1Len.setToolTipText(primeLengthHelp);
final JLabel lblP2Len = getLabel("Prime 2 (q) Length");
lblP2Len.setToolTipText(primeLengthHelp);
txtP1Len = getNumberTextField("0");
txtP1Len.setToolTipText(primeLengthHelp);
txtP1Len.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
try {
final int len1 = Integer.parseInt(txtP1Len.getText().trim());
if (len1 >= 0) {
pLength(len1);
Solver.qLength(0 != len1 ? getSemiprimeLen() - len1 : 0);
txtP2Len.setText("" + Solver.qLength());
}
} catch (Throwable ignored) {
}
}
});
txtP2Len = getNumberTextField("0");
txtP2Len.setToolTipText(primeLengthHelp);
txtP2Len.addActionListener((e) -> {
try {
Solver.qLength(Integer.parseInt(txtP2Len.getText().trim()));
} catch (Throwable ignored) {
}
});
final JButton btnReset = getButton("Reset to Defaults");
btnReset.setToolTipText("This will reset the search settings to defaults (w/o clearing the current semiprime value).");
btnReset.addActionListener((e) -> resetSearchSettings());
final JButton btnRsa100 = getButton("RSA-100");
btnRsa100.setToolTipText("Loads a pre-selected benchmark to run against.");
btnRsa100.addActionListener((e) -> loadBenchmark(RSA_100));
final JButton btnRsa220 = getButton("RSA-220");
btnRsa220.setToolTipText("Loads a pre-selected benchmark to run against.");
btnRsa220.addActionListener((e) -> loadBenchmark(RSA_220));
final JButton btnRsa300 = getButton("RSA-300");
btnRsa300.setToolTipText("Loads a pre-selected benchmark to run against.");
btnRsa300.addActionListener((e) -> loadBenchmark(RSA_300));
final JButton btnRsa2048 = getButton("RSA-2048");
btnRsa2048.setToolTipText("Loads a pre-selected benchmark to run against.");
btnRsa2048.addActionListener((e) -> loadBenchmark(RSA_2048));
final JButton btnUnknownLen = getButton("Prime Lengths: Unknown");
btnUnknownLen.setToolTipText("Prime factor lengths are unknown, so search full space.");
btnUnknownLen.addActionListener((e) -> {
txtP1Len.setText("0");
txtP2Len.setText("0");
});
final JButton btnRsaLen = getButton("Prime Lengths: N/2");
btnRsaLen.setToolTipText("If you know the lengths of your primes in advance, you can greatly aid the search.");
btnRsaLen.addActionListener((e) -> {
try {
final int len = getSemiprimeLen();
txtP1Len.setText("" + ((len / 2) + (0 == len % 2 ? 0 : 1)));
txtP2Len.setText("" + ((len / 2) + (0 == len % 2 ? 0 : 1)));
} catch (Throwable ignored) {
}
});
final JPanel pnlLengths = new JPanel(new GridLayout(1, 2));
pnlLengths.add(btnUnknownLen);
pnlLengths.add(btnRsaLen);
// ///////////////////////////////////
btnSearch = getButton("Start Local Search");
btnSearch.setIcon(icnNodeMedium);
btnSearch.addActionListener(e -> {
try {
// prevent multiple clicks
btnSearch.setEnabled(false);
// interrupt any previous solver and wait for termination
if (!isSearching.compareAndSet(false, true)) {
final Solver solver = solver();
// if there's a pending search, try to cancel it
if (null != solver) {
btnPause.setEnabled(false);
btnResume.setEnabled(false);
if (solver.solving()) {
solver.interruptAndJoin();
Solver.release();
Log.o("search cancelled by user");
}
try {
solver.join();
isSearching.set(false);
btnSearch.setText("Start Local Search");
} catch (Throwable ignored) {
}
}
// remember to re-enable the button no matter what happened
btnSearch.setEnabled(true);
return;
}
// move to main screen to view search progress or init errors
btnSearch.setText("Preparing search...");
// set the solver according to user prefs
try {
Solver.heuristics(Stream.of(chkHeuristics).filter(JCheckBox::isSelected).map(c -> Heuristic.fromFormattedName(c.getText())).toArray(Heuristic[]::new));
Solver.stats(chkPeriodicStats.isSelected());
Solver.detailedStats(chkDetailedStats.isSelected());
Solver.favorPerformance(chkFavorPerformance.isSelected());
Solver.compressMemory(chkCompressMemory.isSelected());
Solver.restrictDisk(chkRestrictDisk.isSelected());
Solver.restrictNetwork(chkRestrictNetwork.isSelected());
Solver.background(chkBackground.isSelected());
Solver.printAllNodes(chkPrintAllNodes.isSelected());
Solver.processors(sldProcessors.getValue());
Solver.processorCap(sldProcessorCap.getValue());
Solver.memoryCap(sldMemoryCap.getValue());
Solver.networkHost(false);
Solver.networkSearch(false);
Solver.csv(chkWriteCsv.isSelected() ? new PrintWriter("search-results.csv") : null);
} catch (Throwable t) {
Log.e(t);
throw new NullPointerException();
}
// try to parse any fixed prime lengths
try {
Solver.pLength(Integer.parseInt(clean(txtP1Len.getText())));
} catch (Throwable t) {
throw new NullPointerException("prime 1 len invalid");
}
try {
Solver.qLength(Integer.parseInt(clean(txtP2Len.getText())));
} catch (Throwable t) {
throw new NullPointerException("prime 2 len invalid");
}
// grab the semiprime options
int spBase = DEFAULT_SEMIPRIME_BASE;
try {
spBase = Integer.parseInt(clean(txtSemiprimeBase.getText()));
} catch (Throwable t) {
Log.e("semiprime base invalid");
txtSemiprimeBase.setText("" + DEFAULT_SEMIPRIME_BASE);
return;
}
if (spBase < 2) {
Log.e("semiprime base < 2");
txtSemiprimeBase.setText("" + DEFAULT_SEMIPRIME_BASE);
return;
}
int internalBase = DEFAULT_INTERNAL_BASE;
try {
internalBase = Integer.parseInt(clean(txtInternalBase.getText()));
} catch (Throwable t) {
Log.e("provided internal base was invalid, defaulting to " + DEFAULT_INTERNAL_BASE);
txtInternalBase.setText("" + DEFAULT_INTERNAL_BASE);
}
if (internalBase < 2) {
Log.e("internal base cannot be < 2, defaulting to " + DEFAULT_INTERNAL_BASE);
txtInternalBase.setText("" + DEFAULT_INTERNAL_BASE);
return;
}
// create a new solver based upon user request and launch it
final String sp = clean(txtSemiprime.getText());
if (null == sp || "".equals(sp))
throw new NullPointerException("you must provide a semiprime to factor");
// ensure gui values reflect underlying state
updateSettings();
// try to start solving
final int base = spBase;
final SwingWorker<Solver.Node, Object> worker = new SwingWorker<Solver.Node, Object>() {
@Override
public Solver.Node doInBackground() {
try {
SwingUtilities.invokeAndWait(() -> {
isSearching.set(true);
btnSearch.setText("Cancel Search");
btnSearch.setEnabled(true);
btnPause.setEnabled(true);
btnResume.setEnabled(false);
pneMain.setSelectedIndex(TAB_CONNECT);
// drop to background
setVisible(false);
});
final Solver solver = new Solver(new BigInteger(sp, base));
solver(solver);
// let user know we are now running collapsed into icon
new Thread(() -> {
try {
Thread.sleep(1000);
if (isSearching.get())
trayIcon.displayMessage("Search Launched", "A search has begun and can be accessed from here.", TrayIcon.MessageType.INFO);
} catch (Throwable ignored) {
}
}).start();
solver.start();
solver.join();
return solver.goal();
} catch (Throwable t) {
Log.e(t);
return null;
} finally {
isSearching.set(false);
}
}
@Override
public void done() {
try {
final Solver.Node n = get();
Log.o("\n********** results **********\n\n" + (null != n ? "s:\t" + n.s + "\np:\t" + n.p + "\nq:\t" + n.q : "no factors could be found, are you sure the input is semiprime" + (Solver.primeLengthsFixed() ? " and the factors are the specified lengths?" : "?")));
SwingUtilities.invokeLater(() -> {
pneMain.setSelectedIndex(TAB_CONNECT);
btnPause.setEnabled(false);
btnResume.setEnabled(false);
btnSearch.setText("Start Local Search");
setVisible(true);
JOptionPane.showMessageDialog(null, null != n ? "Solution found!" : "No solution found.", "Search Complete", null != n ? JOptionPane.INFORMATION_MESSAGE : JOptionPane.ERROR_MESSAGE);
});
} catch (Throwable t) {
Log.e(t);
exit();
}
}
};
// launch the swing worker that will maintain the search
worker.execute();
} catch (Throwable t) {
Log.e(t);
}
});
// ///////////////////////////////////
final JPanel pnlSearchOptions = new JPanel(new GridLayout(3, 3));
pnlSearchOptions.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK), "Search Options", TitledBorder.CENTER, TitledBorder.TOP));
pnlSearchOptions.add(chkFavorPerformance);
pnlSearchOptions.add(chkCompressMemory);
pnlSearchOptions.add(chkRestrictDisk);
pnlSearchOptions.add(chkRestrictNetwork);
pnlSearchOptions.add(chkPeriodicStats);
pnlSearchOptions.add(chkDetailedStats);
pnlSearchOptions.add(chkPrintAllNodes);
pnlSearchOptions.add(chkWriteCsv);
pnlSearchOptions.add(chkBackground);
final JPanel pnlHeuristics = new JPanel(new GridLayout(1 + (chkHeuristics.length / 3), 3));
for (JCheckBox h : chkHeuristics) pnlHeuristics.add(h);
pnlHeuristics.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK), "Select Heuristics", TitledBorder.CENTER, TitledBorder.TOP));
final JPanel pnlSearchHeader = new JPanel(new GridLayout(2, 1, H_GAP, V_GAP));
pnlSearchHeader.add(pnlSearchOptions);
pnlSearchHeader.add(pnlHeuristics);
final JPanel pnlSemiprimeOptions = new JPanel(new GridLayout(4, 3));
pnlSemiprimeOptions.add(lblSemiprimeBase);
pnlSemiprimeOptions.add(txtSemiprimeBase);
pnlSemiprimeOptions.add(lblInternalBase);
pnlSemiprimeOptions.add(txtInternalBase);
pnlSemiprimeOptions.add(lblP1Len);
pnlSemiprimeOptions.add(txtP1Len);
pnlSemiprimeOptions.add(lblP2Len);
pnlSemiprimeOptions.add(txtP2Len);
final JPanel pnlBenchmark = new JPanel(new GridLayout(2, 2));
pnlBenchmark.add(btnRsa100);
pnlBenchmark.add(btnRsa220);
pnlBenchmark.add(btnRsa300);
pnlBenchmark.add(btnRsa2048);
final JPanel pnlButtons0 = new JPanel(new GridLayout(1, 2));
pnlButtons0.add(btnReset);
pnlButtons0.add(pnlBenchmark);
final JPanel pnlButtons1 = new JPanel(new GridLayout(1, 2));
pnlButtons1.add(pnlButtons0);
pnlButtons1.add(pnlLengths);
// //////////////////
final JPanel pnlButtons3 = new JPanel(new GridLayout(1, 2));
final JPanel pnlButtons4 = new JPanel(new GridLayout(1, 1));
// placeholder
pnlButtons3.add(btnPause);
pnlButtons3.add(btnResume);
// placeholder
pnlButtons4.add(btnSearch);
final JPanel pnlButtons2 = new JPanel(new GridLayout(1, 2));
pnlButtons2.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "", TitledBorder.CENTER, TitledBorder.TOP));
pnlButtons2.add(pnlButtons3);
pnlButtons2.add(pnlButtons4);
// //////////////////
final JPanel pnlButtons = new JPanel(new GridLayout(2, 1, H_GAP, V_GAP));
pnlButtons.add(pnlButtons1);
pnlButtons.add(pnlButtons2);
final JPanel pnlSemiprime = new JPanel(new GridLayout(2, 1));
pnlSemiprime.add(pnlSemiprimeOptions);
pnlSemiprime.add(pnlButtons);
pnlSearchFooter = new JPanel(new GridLayout(2, 1));
pnlSearchFooter.add(pneSemiprime);
pnlSearchFooter.add(pnlSemiprime);
pnlSearchFooter.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "<html><center>Semiprime Target<h5>(enter a value to factor)</h5></center></html>", TitledBorder.CENTER, TitledBorder.TOP));
final JPanel pnlSearch = new JPanel(new GridLayout(2, 1, H_GAP / 2, V_GAP / 2));
pnlSearch.add(pnlSearchHeader);
pnlSearch.add(pnlSearchFooter);
// //////////////////////////////////////////////////////////////////////////
// cpu tab
// setup the memory/ processing limit sliders:
final JLabel lblProcessors = getLabel("Processors to use");
sldProcessors = new JSlider(1, processors, prefs.getInt(PROCESSORS_NAME, DEFAULT_PROCESSORS));
sldProcessors.setMajorTickSpacing(1);
sldProcessors.setSnapToTicks(true);
sldProcessors.setPaintTicks(true);
sldProcessors.setPaintLabels(true);
sldProcessors.addChangeListener(c -> {
if (sldProcessors.getValueIsAdjusting())
return;
int val = sldProcessors.getValue();
Solver.processors(val);
Log.o("processors: " + val);
});
final JLabel lblCap = getLabel("Per-processor usage limit (%)");
sldProcessorCap = new JSlider(0, 100, prefs.getInt(PROCESSOR_CAP_NAME, DEFAULT_PROCESSOR_CAP));
sldProcessorCap.setMajorTickSpacing(25);
sldProcessorCap.setMinorTickSpacing(5);
sldProcessorCap.setSnapToTicks(true);
sldProcessorCap.setPaintLabels(true);
sldProcessorCap.setPaintTicks(true);
sldProcessorCap.addChangeListener(c -> {
if (sldProcessorCap.getValueIsAdjusting())
return;
int val = sldProcessorCap.getValue();
Solver.processorCap(val);
Log.o("processorCap: " + val + "%");
});
final JLabel lblMemory = getLabel("Memory usage limit (%)");
sldMemoryCap = new JSlider(0, 100, prefs.getInt(MEMORY_CAP_NAME, DEFAULT_MEMORY_CAP));
sldMemoryCap.setMajorTickSpacing(25);
sldMemoryCap.setMinorTickSpacing(5);
sldMemoryCap.setSnapToTicks(true);
sldMemoryCap.setPaintLabels(true);
sldMemoryCap.setPaintTicks(true);
sldMemoryCap.addChangeListener(c -> {
if (sldMemoryCap.getValueIsAdjusting())
return;
int val = sldMemoryCap.getValue();
Solver.memoryCap(val);
Log.o("memoryCap: " + val + "%");
});
final JLabel lblIdle = getLabel("Idle time until work begins (min)");
sldIdle = new JSlider(0, 30, prefs.getInt(IDLE_MINUTES_NAME, DEFAULT_IDLE_MINUTES));
sldIdle.setMajorTickSpacing(5);
sldIdle.setMinorTickSpacing(1);
sldIdle.setSnapToTicks(true);
sldIdle.setPaintLabels(true);
sldIdle.setPaintTicks(true);
sldIdle.addChangeListener(c -> {
if (sldIdle.getValueIsAdjusting())
return;
int val = sldIdle.getValue();
Log.o("idle delay before search: " + val + " minutes");
});
final JButton btnResetCpu = getButton("Reset to Defaults");
btnResetCpu.addActionListener(l -> {
final int result = JOptionPane.showConfirmDialog(null, "Are you sure you want to reset all CPU settings to defaults?", "Confirm Reset", JOptionPane.YES_NO_OPTION);
if (JOptionPane.YES_OPTION == result)
resetCpuSettings();
});
// setup the left-side:
final JPanel pnlCpuLeft = new JPanel(new GridLayout(7, 1, H_GAP, V_GAP));
pnlCpuLeft.add(lblProcessors);
pnlCpuLeft.add(sldProcessors);
pnlCpuLeft.add(lblCap);
pnlCpuLeft.add(sldProcessorCap);
pnlCpuLeft.add(getLabel(""));
pnlCpuLeft.add(getLabel(""));
pnlCpuLeft.add(btnResetCpu);
// setup the right-side:
final JPanel pnlCpuRight = new JPanel(new GridLayout(7, 1, H_GAP, V_GAP));
// auto start with system?
chkAutoStart = getCheckBox("auto-start with system", prefs.getBoolean(AUTOSTART_NAME, DEFAULT_AUTOSTART));
chkAutoStart.addActionListener(l -> Log.o("autostart: " + (chkAutoStart.isSelected() ? "yes" : "no")));
final JPanel pnlChkBoxes = new JPanel(new GridLayout(1, 1, H_GAP, V_GAP));
pnlChkBoxes.add(chkAutoStart);
pnlCpuRight.add(lblMemory);
pnlCpuRight.add(sldMemoryCap);
pnlCpuRight.add(lblIdle);
pnlCpuRight.add(sldIdle);
pnlCpuRight.add(getLabel(""));
pnlCpuRight.add(getLabel(""));
pnlCpuRight.add(pnlChkBoxes);
// create the full CPU panel
final JPanel pnlCpu = new JPanel(new GridLayout(1, 2, H_GAP, V_GAP));
pnlCpu.add(pnlCpuLeft);
pnlCpu.add(pnlCpuRight);
// //////////////////////////////////////////////////////////////////////////
// miscellaneous tab
final JButton btnResetAll = getButton("Reset all settings to defaults");
btnResetAll.addActionListener((e) -> {
resetSettings();
pneMain.setSelectedIndex(TAB_CONNECT);
});
final JButton btnSaveAll = getButton("Save all current settings");
btnSaveAll.addActionListener((e) -> {
saveSettings();
pneMain.setSelectedIndex(TAB_CONNECT);
});
final JButton btnLoadAll = getButton("Load all stored settings");
btnLoadAll.addActionListener((e) -> {
loadSettings();
pneMain.setSelectedIndex(TAB_CONNECT);
});
final JPanel pnlMiscBtns = new JPanel(new GridLayout(4, 3));
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
pnlMiscBtns.add(btnSaveAll);
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
pnlMiscBtns.add(btnLoadAll);
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
pnlMiscBtns.add(btnResetAll);
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
// placeholder
pnlMiscBtns.add(Box.createHorizontalBox());
final JPanel pnlMisc = new JPanel(new GridLayout(2, 1));
pnlMisc.add(getLabel("You will find additional settings in this tab as they become available."));
pnlMisc.add(pnlMiscBtns);
// //////////////////////////////////////////////////////////////////////////
// add tabs to frame
// create the tabbed panes
pneMain = new JTabbedPane();
pneMain.setFocusable(false);
pneMain.setBorder(null);
pneMain.addTab("", icnNet, pnlNet, "Connect to a compute server");
pneMain.addTab("", icnNode, pnlSearch, "Search settings");
pneMain.addTab("", icnCpu, pnlCpu, "Hardware settings");
pneMain.addTab("", icnMisc, pnlMisc, "Miscellaneous settings");
// add the panel to the frame and show everything
getContentPane().add(pneMain);
resetFrame();
// //////////////////////////////////////////////////////////////////////////
// setup the system tray, if supported
boolean useTray = SystemTray.isSupported();
if (useTray) {
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
systemTray = SystemTray.getSystemTray();
trayIcon = new TrayIcon(icnNodeSmall.getImage(), "Semiprime Factorization v" + Solver.VERSION);
final PopupMenu popup = new PopupMenu();
final MenuItem show = new MenuItem("Hide App");
final Runnable trayVisibleToggle = () -> {
final boolean visible = !isVisible();
setVisible(visible);
show.setLabel(visible ? "Hide App" : "Show App");
};
show.addActionListener(l -> trayVisibleToggle.run());
final MenuItem pause = new MenuItem("Pause");
final MenuItem resume = new MenuItem("Resume");
resume.setEnabled(false);
pause.addActionListener(l -> {
pause.setEnabled(false);
pause();
trayIcon.displayMessage("Paused", "All work has been paused.", TrayIcon.MessageType.INFO);
resume.setEnabled(true);
});
resume.addActionListener(l -> {
resume.setEnabled(false);
resume();
trayIcon.displayMessage("Resumed", "All work has been resumed.", TrayIcon.MessageType.INFO);
pause.setEnabled(true);
});
final MenuItem quit = new MenuItem("Quit Discarding Changes");
quit.addActionListener(l -> exit(false));
final MenuItem saveAndQuit = new MenuItem("Save & Quit");
saveAndQuit.addActionListener(l -> exit());
trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
final int btn = e.getButton();
final boolean osx = OS.contains("OS X");
if ((btn == MouseEvent.BUTTON1 && !osx) || (btn != MouseEvent.BUTTON1 && osx))
trayVisibleToggle.run();
}
});
popup.add(show);
popup.addSeparator();
popup.add(pause);
popup.add(resume);
popup.addSeparator();
popup.add(quit);
popup.add(saveAndQuit);
trayIcon.setPopupMenu(popup);
try {
systemTray.add(trayIcon);
} catch (Throwable t) {
useTray = false;
Log.e("couldn't create tray icon, will exit on window close immediately");
}
}
// on close, kill the server connection if there is no tray icon in use
if (!useTray)
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
exit();
}
});
// show the gui
setVisible(true);
toFront();
// attempt to load stored settings
Log.disable();
loadSettings();
Log.enable();
// show greeting
Log.o("<h3>(Thank you)<sup>2048</sup> for helping my research!</h3>" + "<br>" + "If you're computer cracks a target number, you will be credited in the publication (assuming you provided an email I can reach you at)." + "<br>" + "If you're interested in learning exactly what this software does and why, checkout the \"About\" menu.");
// collect garbage and report memory info
runtime.gc();
final double freeMemory = (double) runtime.freeMemory() / toGb;
final double totalMemory = (double) runtime.totalMemory() / toGb;
final double maxMemory = (double) runtime.maxMemory() / toGb;
final DecimalFormat formatter = new DecimalFormat("#.##");
// report discovered system stats
Log.o("operating system: " + OS + ", version " + System.getProperty("os.version") + "\n" + "current java version: " + version + ", required: 1.8+\n" + "note: all memory values reported are relative to the JVM, and were reported immediately after invoking the GC\n" + "free memory: ~" + formatter.format(freeMemory) + " (Gb)\n" + "total memory: ~" + formatter.format(totalMemory) + " (Gb)\n" + "max memory: ~" + formatter.format(maxMemory) + " (Gb)\n" + "free memory / total memory: " + formatter.format(100.0 * (freeMemory / totalMemory)) + "%\n" + "total memory / max memory: " + formatter.format(100.0 * (totalMemory / maxMemory)) + "%\n" + "always work: " + chkBackground.isSelected() + "\n" + "autostart: " + chkAutoStart.isSelected() + "\n" + "available processors: " + processors);
return true;
}
use of javax.swing.text.html.HTMLEditorKit in project intellij-community by JetBrains.
the class IdeTooltipManager method initPane.
public static JEditorPane initPane(@NonNls Html html, final HintHint hintHint, @Nullable final JLayeredPane layeredPane) {
final Ref<Dimension> prefSize = new Ref<>(null);
@NonNls String text = HintUtil.prepareHintText(html, hintHint);
final boolean[] prefSizeWasComputed = { false };
final JEditorPane pane = new JEditorPane() {
@Override
public Dimension getPreferredSize() {
if (!isShowing() && layeredPane != null) {
AppUIUtil.targetToDevice(this, layeredPane);
}
if (!prefSizeWasComputed[0] && hintHint.isAwtTooltip()) {
JLayeredPane lp = layeredPane;
if (lp == null) {
JRootPane rootPane = UIUtil.getRootPane(this);
if (rootPane != null) {
lp = rootPane.getLayeredPane();
}
}
Dimension size;
if (lp != null) {
size = lp.getSize();
prefSizeWasComputed[0] = true;
} else {
size = ScreenUtil.getScreenRectangle(0, 0).getSize();
}
int fitWidth = (int) (size.width * 0.8);
Dimension prefSizeOriginal = super.getPreferredSize();
if (prefSizeOriginal.width > fitWidth) {
setSize(new Dimension(fitWidth, Integer.MAX_VALUE));
Dimension fixedWidthSize = super.getPreferredSize();
Dimension minSize = super.getMinimumSize();
prefSize.set(new Dimension(fitWidth > minSize.width ? fitWidth : minSize.width, fixedWidthSize.height));
} else {
prefSize.set(new Dimension(prefSizeOriginal));
}
}
Dimension s = prefSize.get() != null ? new Dimension(prefSize.get()) : super.getPreferredSize();
Border b = getBorder();
if (b != null) {
JBInsets.addTo(s, b.getBorderInsets(this));
}
return s;
}
@Override
public void setPreferredSize(Dimension preferredSize) {
super.setPreferredSize(preferredSize);
prefSize.set(preferredSize);
}
};
final HTMLEditorKit.HTMLFactory factory = new HTMLEditorKit.HTMLFactory() {
@Override
public View create(Element elem) {
AttributeSet attrs = elem.getAttributes();
Object elementName = attrs.getAttribute(AbstractDocument.ElementNameAttribute);
Object o = elementName != null ? null : attrs.getAttribute(StyleConstants.NameAttribute);
if (o instanceof HTML.Tag) {
HTML.Tag kind = (HTML.Tag) o;
if (kind == HTML.Tag.HR) {
return new CustomHrView(elem, hintHint.getTextForeground());
}
}
return super.create(elem);
}
};
HTMLEditorKit kit = new HTMLEditorKit() {
@Override
public ViewFactory getViewFactory() {
return factory;
}
};
pane.setEditorKit(kit);
pane.setText(text);
pane.setCaretPosition(0);
pane.setEditable(false);
if (hintHint.isOwnBorderAllowed()) {
setBorder(pane);
setColors(pane);
} else {
pane.setBorder(null);
}
if (!hintHint.isAwtTooltip()) {
prefSizeWasComputed[0] = true;
}
final boolean opaque = hintHint.isOpaqueAllowed();
pane.setOpaque(opaque);
if (UIUtil.isUnderNimbusLookAndFeel() && !opaque) {
pane.setBackground(UIUtil.TRANSPARENT_COLOR);
} else {
pane.setBackground(hintHint.getTextBackground());
}
return pane;
}
use of javax.swing.text.html.HTMLEditorKit in project intellij-community by JetBrains.
the class UnusedDeclarationPresentation method getCustomPreviewPanel.
@Override
public JComponent getCustomPreviewPanel(RefEntity entity) {
final Project project = entity.getRefManager().getProject();
JEditorPane htmlView = new JEditorPane() {
@Override
public String getToolTipText(MouseEvent evt) {
int pos = viewToModel(evt.getPoint());
if (pos >= 0) {
HTMLDocument hdoc = (HTMLDocument) getDocument();
javax.swing.text.Element e = hdoc.getCharacterElement(pos);
AttributeSet a = e.getAttributes();
SimpleAttributeSet value = (SimpleAttributeSet) a.getAttribute(HTML.Tag.A);
if (value != null) {
String objectPackage = (String) value.getAttribute("qualifiedname");
if (objectPackage != null) {
return objectPackage;
}
}
}
return null;
}
};
htmlView.setContentType(UIUtil.HTML_MIME);
htmlView.setEditable(false);
htmlView.setOpaque(false);
htmlView.setBackground(UIUtil.getLabelBackground());
htmlView.addHyperlinkListener(new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
URL url = e.getURL();
if (url == null) {
return;
}
@NonNls String ref = url.getRef();
int offset = Integer.parseInt(ref);
String fileURL = url.toExternalForm();
fileURL = fileURL.substring(0, fileURL.indexOf('#'));
VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(fileURL);
if (vFile == null) {
vFile = VfsUtil.findFileByURL(url);
}
if (vFile != null) {
final OpenFileDescriptor descriptor = new OpenFileDescriptor(project, vFile, offset);
FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
}
}
});
final StyleSheet css = ((HTMLEditorKit) htmlView.getEditorKit()).getStyleSheet();
css.addRule("p.problem-description-group {text-indent: " + JBUI.scale(9) + "px;font-weight:bold;}");
css.addRule("div.problem-description {margin-left: " + JBUI.scale(9) + "px;}");
css.addRule("ul {margin-left:" + JBUI.scale(10) + "px;text-indent: 0}");
css.addRule("code {font-family:" + UIUtil.getLabelFont().getFamily() + "}");
final StringBuffer buf = new StringBuffer();
getComposer().compose(buf, entity, false);
final String text = buf.toString();
SingleInspectionProfilePanel.readHTML(htmlView, SingleInspectionProfilePanel.toHTML(htmlView, text, false));
return ScrollPaneFactory.createScrollPane(htmlView, true);
}
use of javax.swing.text.html.HTMLEditorKit in project intellij-community by JetBrains.
the class UIUtil method getHTMLEditorKit.
public static HTMLEditorKit getHTMLEditorKit(boolean noGapsBetweenParagraphs) {
Font font = getLabelFont();
@NonNls String family = !SystemInfo.isWindows && font != null ? font.getFamily() : "Tahoma";
final int size = font != null ? font.getSize() : JBUI.scale(11);
String customCss = String.format("body, div, p { font-family: %s; font-size: %s; }", family, size);
if (noGapsBetweenParagraphs) {
customCss += " p { margin-top: 0; }";
}
final StyleSheet style = new StyleSheet();
style.addStyleSheet(isUnderDarcula() ? (StyleSheet) UIManager.getDefaults().get("StyledEditorKit.JBDefaultStyle") : DEFAULT_HTML_KIT_CSS);
style.addRule(customCss);
return new HTMLEditorKit() {
@Override
public StyleSheet getStyleSheet() {
return style;
}
};
}
Aggregations