mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-825 - Task Dialog - fixed expanding task dialog
This commit is contained in:
parent
ec22f78db9
commit
9c9dcc927a
5 changed files with 102 additions and 64 deletions
|
@ -485,7 +485,7 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
* NOTE: method may only be invoked within the analysis thread
|
* NOTE: method may only be invoked within the analysis thread
|
||||||
* (i.e., by an Analyzer or AnalysisWorker). Care must be taken to control depth
|
* (i.e., by an Analyzer or AnalysisWorker). Care must be taken to control depth
|
||||||
* of yield, although this may be difficult to control.
|
* of yield, although this may be difficult to control.
|
||||||
* @param monitor
|
* @param monitor the monitor
|
||||||
*/
|
*/
|
||||||
private void yield(Integer limitPriority, TaskMonitor monitor) {
|
private void yield(Integer limitPriority, TaskMonitor monitor) {
|
||||||
|
|
||||||
|
@ -516,7 +516,7 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
* (i.e., lower values correspond to higher priority) will be permitted to run. A value
|
* (i.e., lower values correspond to higher priority) will be permitted to run. A value
|
||||||
* of null will allow all pending analysis to complete (excluding any tasks which had
|
* of null will allow all pending analysis to complete (excluding any tasks which had
|
||||||
* previously yielded).
|
* previously yielded).
|
||||||
* @param monitor
|
* @param monitor the monitor
|
||||||
* @throws IllegalStateException if not invoked from the analysis thread.
|
* @throws IllegalStateException if not invoked from the analysis thread.
|
||||||
*/
|
*/
|
||||||
public void waitForAnalysis(final Integer limitPriority, TaskMonitor monitor) {
|
public void waitForAnalysis(final Integer limitPriority, TaskMonitor monitor) {
|
||||||
|
@ -626,7 +626,7 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
* yield method so that their limit-priority may be established during the yield.
|
* yield method so that their limit-priority may be established during the yield.
|
||||||
* <br>
|
* <br>
|
||||||
* If analysis is performed, a summary of task execution times will be printed to the log.
|
* If analysis is performed, a summary of task execution times will be printed to the log.
|
||||||
* @param monitor
|
* @param monitor the monitor
|
||||||
*/
|
*/
|
||||||
public void startAnalysis(TaskMonitor monitor) {
|
public void startAnalysis(TaskMonitor monitor) {
|
||||||
startAnalysis(monitor, true);
|
startAnalysis(monitor, true);
|
||||||
|
@ -642,7 +642,7 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
* performed in which all queued tasks of a higher priority (smaller priority value) than the current
|
* performed in which all queued tasks of a higher priority (smaller priority value) than the current
|
||||||
* task will be executed prior to this method returning. AnalysisWorker's should use the
|
* task will be executed prior to this method returning. AnalysisWorker's should use the
|
||||||
* yield method so that their limit-priority may be established during the yield.
|
* yield method so that their limit-priority may be established during the yield.
|
||||||
* @param monitor
|
* @param monitor the monitor
|
||||||
* @param printTaskTimes if true and analysis is performed, a summary of task execution times
|
* @param printTaskTimes if true and analysis is performed, a summary of task execution times
|
||||||
* will be printed to the log.
|
* will be printed to the log.
|
||||||
*/
|
*/
|
||||||
|
@ -722,7 +722,7 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start auto-analysis if it is ENABLED and not yet running.
|
* Start auto-analysis if it is ENABLED and not yet running.
|
||||||
* @param monitor
|
* @param monitor the monitor
|
||||||
* @param yield if true the current thread is the analysis thread and is yielding to the currently
|
* @param yield if true the current thread is the analysis thread and is yielding to the currently
|
||||||
* executing task.
|
* executing task.
|
||||||
* @param limitPriority the threshold priority value. All queued tasks with a priority value
|
* @param limitPriority the threshold priority value. All queued tasks with a priority value
|
||||||
|
@ -1204,7 +1204,8 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
/**
|
/**
|
||||||
* Get the time taken by a named task
|
* Get the time taken by a named task
|
||||||
* The names of tasks that have run can be retrieved using getTimedTasks
|
* The names of tasks that have run can be retrieved using getTimedTasks
|
||||||
* @param taskName
|
* @param map the times by task names
|
||||||
|
* @param taskName the task name
|
||||||
* @return the time taken by a named task
|
* @return the time taken by a named task
|
||||||
*/
|
*/
|
||||||
public long getTaskTime(Map<String, Long> map, String taskName) {
|
public long getTaskTime(Map<String, Long> map, String taskName) {
|
||||||
|
@ -1230,8 +1231,7 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
if (currentTime > 0) {
|
if (currentTime > 0) {
|
||||||
totalTime += currentTime;
|
totalTime += currentTime;
|
||||||
}
|
}
|
||||||
Long l = new Long(totalTime);
|
return totalTime;
|
||||||
return l.longValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addToTaskTime(String taskName, long time) {
|
private void addToTaskTime(String taskName, long time) {
|
||||||
|
@ -1252,7 +1252,8 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print out the time for each task that ran for this auto analysis run.
|
* Get a summary of the time for each task that ran for this auto analysis run
|
||||||
|
* @return the string summary
|
||||||
*/
|
*/
|
||||||
public String getTaskTimesString() {
|
public String getTaskTimesString() {
|
||||||
|
|
||||||
|
@ -1331,11 +1332,12 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
* follow-on analysis of those changes. If false it is critical that the worker be associated with a modal
|
* follow-on analysis of those changes. If false it is critical that the worker be associated with a modal
|
||||||
* task dialog which will prevent unrelated concurrent changes being made to the program while
|
* task dialog which will prevent unrelated concurrent changes being made to the program while
|
||||||
* the worker is active.
|
* the worker is active.
|
||||||
* @param workerMonitor
|
* @param workerMonitor the worker's monitor
|
||||||
* @return boolean value returned by worker.analysisWorkerCallback
|
* @return boolean value returned by worker.analysisWorkerCallback
|
||||||
* @throws InvocationTargetException if worker throws exception while running (see cause)
|
* @throws InvocationTargetException if worker throws exception while running (see cause)
|
||||||
* @throws InterruptedException if caller's thread is interrupted. If this occurs a cancel
|
* @throws InterruptedException if caller's thread is interrupted. If this occurs a cancel
|
||||||
* condition will be forced on the workerMonitor so that the worker will stop running.
|
* condition will be forced on the workerMonitor so that the worker will stop running.
|
||||||
|
* @throws CancelledException if the job is cancelled
|
||||||
* @see AnalysisPriority for priority values
|
* @see AnalysisPriority for priority values
|
||||||
*/
|
*/
|
||||||
public boolean scheduleWorker(AnalysisWorker worker, Object workerContext,
|
public boolean scheduleWorker(AnalysisWorker worker, Object workerContext,
|
||||||
|
@ -1472,17 +1474,17 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
|
|
||||||
private class JointTaskMonitor implements TaskMonitor {
|
private class JointTaskMonitor implements TaskMonitor {
|
||||||
|
|
||||||
TaskMonitor dominantMonitor;
|
private TaskMonitor primaryMonitor;
|
||||||
TaskMonitor slaveMonitor;
|
private TaskMonitor secondaryMonitor;
|
||||||
|
|
||||||
JointTaskMonitor(TaskMonitor dominantMonitor, TaskMonitor slaveMonitor) {
|
JointTaskMonitor(TaskMonitor primaryMonitor, TaskMonitor secondaryMonitor) {
|
||||||
this.dominantMonitor = dominantMonitor;
|
this.primaryMonitor = primaryMonitor;
|
||||||
this.slaveMonitor = slaveMonitor;
|
this.secondaryMonitor = secondaryMonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return dominantMonitor.isCancelled() || slaveMonitor.isCancelled();
|
return primaryMonitor.isCancelled() || secondaryMonitor.isCancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1502,86 +1504,86 @@ public class AutoAnalysisManager implements DomainObjectListener, DomainObjectCl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMessage(String message) {
|
public void setMessage(String message) {
|
||||||
dominantMonitor.setMessage(message);
|
primaryMonitor.setMessage(message);
|
||||||
slaveMonitor.setMessage(message);
|
secondaryMonitor.setMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return dominantMonitor.getMessage();
|
return primaryMonitor.getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgress(long value) {
|
public void setProgress(long value) {
|
||||||
dominantMonitor.setProgress(value);
|
primaryMonitor.setProgress(value);
|
||||||
slaveMonitor.setProgress(value);
|
secondaryMonitor.setProgress(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(long max) {
|
public void initialize(long max) {
|
||||||
dominantMonitor.initialize(max);
|
primaryMonitor.initialize(max);
|
||||||
slaveMonitor.initialize(max);
|
secondaryMonitor.initialize(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMaximum(long max) {
|
public void setMaximum(long max) {
|
||||||
dominantMonitor.setMaximum(max);
|
primaryMonitor.setMaximum(max);
|
||||||
slaveMonitor.setMaximum(max);
|
secondaryMonitor.setMaximum(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getMaximum() {
|
public long getMaximum() {
|
||||||
return Math.max(dominantMonitor.getMaximum(), slaveMonitor.getMaximum());
|
return Math.max(primaryMonitor.getMaximum(), secondaryMonitor.getMaximum());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkCanceled() throws CancelledException {
|
public void checkCanceled() throws CancelledException {
|
||||||
dominantMonitor.checkCanceled();
|
primaryMonitor.checkCanceled();
|
||||||
slaveMonitor.checkCanceled();
|
secondaryMonitor.checkCanceled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void incrementProgress(long incrementAmount) {
|
public void incrementProgress(long incrementAmount) {
|
||||||
dominantMonitor.incrementProgress(incrementAmount);
|
primaryMonitor.incrementProgress(incrementAmount);
|
||||||
slaveMonitor.incrementProgress(incrementAmount);
|
secondaryMonitor.incrementProgress(incrementAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getProgress() {
|
public long getProgress() {
|
||||||
return Math.max(dominantMonitor.getProgress(), slaveMonitor.getProgress());
|
return Math.max(primaryMonitor.getProgress(), secondaryMonitor.getProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
dominantMonitor.cancel();
|
primaryMonitor.cancel();
|
||||||
slaveMonitor.cancel();
|
secondaryMonitor.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCancelledListener(CancelledListener listener) {
|
public void addCancelledListener(CancelledListener listener) {
|
||||||
dominantMonitor.addCancelledListener(listener);
|
primaryMonitor.addCancelledListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCancelledListener(CancelledListener listener) {
|
public void removeCancelledListener(CancelledListener listener) {
|
||||||
dominantMonitor.addCancelledListener(listener);
|
primaryMonitor.addCancelledListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCancelEnabled(boolean enable) {
|
public void setCancelEnabled(boolean enable) {
|
||||||
dominantMonitor.setCancelEnabled(enable);
|
primaryMonitor.setCancelEnabled(enable);
|
||||||
slaveMonitor.setCancelEnabled(enable);
|
secondaryMonitor.setCancelEnabled(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelEnabled() {
|
public boolean isCancelEnabled() {
|
||||||
return dominantMonitor.isCancelEnabled();
|
return primaryMonitor.isCancelEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearCanceled() {
|
public void clearCanceled() {
|
||||||
dominantMonitor.clearCanceled();
|
primaryMonitor.clearCanceled();
|
||||||
slaveMonitor.clearCanceled();
|
secondaryMonitor.clearCanceled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,7 @@ import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.Task;
|
import ghidra.util.task.*;
|
||||||
import ghidra.util.task.TaskMonitor;
|
|
||||||
|
|
||||||
class LoadPdbTask extends Task {
|
class LoadPdbTask extends Task {
|
||||||
private File pdbFile;
|
private File pdbFile;
|
||||||
|
@ -59,8 +58,15 @@ class LoadPdbTask extends Task {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(final TaskMonitor monitor) {
|
public void run(final TaskMonitor monitor) {
|
||||||
final MessageLog log = new MessageLog();
|
|
||||||
|
|
||||||
|
WrappingTaskMonitor wrappedMonitor = new WrappingTaskMonitor(monitor) {
|
||||||
|
@Override
|
||||||
|
public void initialize(long max) {
|
||||||
|
// don't let called clients change our monitor type; we don't show progress
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageLog log = new MessageLog();
|
||||||
AnalysisWorker worker = new AnalysisWorker() {
|
AnalysisWorker worker = new AnalysisWorker() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -74,11 +80,11 @@ class LoadPdbTask extends Task {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (useMsDiaParser) {
|
if (useMsDiaParser) {
|
||||||
if (!parseWithMsDiaParser(log, monitor)) {
|
if (!parseWithMsDiaParser(log, wrappedMonitor)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!parseWithNewParser(log, monitor)) {
|
else if (!parseWithNewParser(log, wrappedMonitor)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
analyzeSymbols(currentMonitor, log);
|
analyzeSymbols(currentMonitor, log);
|
||||||
|
@ -92,7 +98,7 @@ class LoadPdbTask extends Task {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AutoAnalysisManager.getAnalysisManager(program)
|
AutoAnalysisManager.getAnalysisManager(program)
|
||||||
.scheduleWorker(worker, null, true, monitor);
|
.scheduleWorker(worker, null, true, wrappedMonitor);
|
||||||
if (log.hasMessages()) {
|
if (log.hasMessages()) {
|
||||||
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Load PDB File",
|
MultiLineMessageDialog dialog = new MultiLineMessageDialog("Load PDB File",
|
||||||
"There were warnings/errors loading the PDB file.", log.toString(),
|
"There were warnings/errors loading the PDB file.", log.toString(),
|
||||||
|
|
|
@ -17,6 +17,8 @@ package pdb;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
|
|
||||||
import docking.action.MenuData;
|
import docking.action.MenuData;
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
import docking.widgets.filechooser.GhidraFileChooser;
|
import docking.widgets.filechooser.GhidraFileChooser;
|
||||||
|
@ -36,6 +38,7 @@ import ghidra.program.util.GhidraProgramUtilities;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.filechooser.ExtensionFileFilter;
|
import ghidra.util.filechooser.ExtensionFileFilter;
|
||||||
|
import ghidra.util.task.TaskBuilder;
|
||||||
import ghidra.util.task.TaskLauncher;
|
import ghidra.util.task.TaskLauncher;
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
@ -134,8 +137,12 @@ public class PdbPlugin extends Plugin {
|
||||||
|
|
||||||
// note: We intentionally use a 0-delay here. Our underlying task may show modal
|
// note: We intentionally use a 0-delay here. Our underlying task may show modal
|
||||||
// dialog prompts. We want the task progress dialog to be showing before any
|
// dialog prompts. We want the task progress dialog to be showing before any
|
||||||
// promts appear.
|
// prompts appear.
|
||||||
|
|
||||||
LoadPdbTask task = new LoadPdbTask(program, pdb, useMsDiaParser, restrictions, service);
|
LoadPdbTask task = new LoadPdbTask(program, pdb, useMsDiaParser, restrictions, service);
|
||||||
|
TaskBuilder.withTask(task)
|
||||||
|
.setStatusTextAlignment(SwingConstants.LEADING)
|
||||||
|
.setLaunchDelay(0);
|
||||||
new TaskLauncher(task, null, 0);
|
new TaskLauncher(task, null, 0);
|
||||||
}
|
}
|
||||||
catch (Exception pe) {
|
catch (Exception pe) {
|
||||||
|
|
|
@ -33,37 +33,40 @@ import util.CollectionUtils;
|
||||||
* the {@link Task} interface, which means less boiler-plate code.
|
* the {@link Task} interface, which means less boiler-plate code.
|
||||||
*
|
*
|
||||||
* <P>An example of usage:
|
* <P>An example of usage:
|
||||||
* <pre>{@literal
|
* <pre>
|
||||||
* MonitoredRunnable r =
|
* {@literal
|
||||||
* monitor -> doWork(parameter, monitor);
|
* MonitoredRunnable r =
|
||||||
* new TaskBuilder("Task Title", r)
|
* monitor -> doWork(parameter, monitor);
|
||||||
* .setHasProgress(true)
|
*
|
||||||
* .setCanCancel(true)
|
* new TaskBuilder("Task Title", r)
|
||||||
* .setStatusTextAlignment(SwingConstants.LEADING)
|
* .setHasProgress(true)
|
||||||
* .launchModal();
|
* .setCanCancel(true)
|
||||||
|
* .setStatusTextAlignment(SwingConstants.LEADING)
|
||||||
|
* .launchModal();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* Or,
|
* Or,
|
||||||
*
|
*
|
||||||
* <pre>{@literal
|
* <pre>
|
||||||
* TaskBuilder.withRunnable(monitor -> doWork(parameter, monitor))
|
* {@literal
|
||||||
* .setTitle("Task Title")
|
* TaskBuilder.withRunnable(monitor -> doWork(parameter, monitor))
|
||||||
* .setHasProgress(true)
|
* .setTitle("Task Title")
|
||||||
* .setCanCancel(true)
|
* .setHasProgress(true)
|
||||||
* .setStatusTextAlignment(SwingConstants.LEADING)
|
* .setCanCancel(true)
|
||||||
* .launchModal();
|
* .setStatusTextAlignment(SwingConstants.LEADING)
|
||||||
|
* .launchModal();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* Or,
|
* Or,
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* TaskBuilder.withTask(new AwesomeTask(awesomeStuff)).launchModal();
|
* TaskBuilder.withTask(new AwesomeTask(awesomeStuff)).launchModal();
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* Or,
|
* Or,
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* {@link TaskLauncher#launch(Task) TaskLauncher.launch}(new AwesomeTask(awesomeStuff));
|
* {@link TaskLauncher#launch(Task) TaskLauncher.launch}(new AwesomeTask(awesomeStuff));
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
|
|
@ -205,11 +205,26 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
|
||||||
return userSaysYes;
|
return userSaysYes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isInstalled(Component c) {
|
||||||
|
Component[] components = mainPanel.getComponents();
|
||||||
|
for (Component component : components) {
|
||||||
|
if (c == component) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the panel that contains the progress bar to the dialog
|
* Adds the panel that contains the progress bar to the dialog
|
||||||
*/
|
*/
|
||||||
private void installProgressMonitor() {
|
private void installProgressMonitor() {
|
||||||
Swing.runIfSwingOrRunLater(() -> {
|
Swing.runIfSwingOrRunLater(() -> {
|
||||||
|
|
||||||
|
if (isInstalled(monitorComponent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mainPanel.removeAll();
|
mainPanel.removeAll();
|
||||||
mainPanel.add(monitorComponent, BorderLayout.CENTER);
|
mainPanel.add(monitorComponent, BorderLayout.CENTER);
|
||||||
repack();
|
repack();
|
||||||
|
@ -222,6 +237,11 @@ public class TaskDialog extends DialogComponentProvider implements TaskMonitor {
|
||||||
*/
|
*/
|
||||||
private void installActivityDisplay() {
|
private void installActivityDisplay() {
|
||||||
Swing.runIfSwingOrRunLater(() -> {
|
Swing.runIfSwingOrRunLater(() -> {
|
||||||
|
|
||||||
|
if (isInstalled(activityPanel)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mainPanel.removeAll();
|
mainPanel.removeAll();
|
||||||
mainPanel.add(activityPanel, BorderLayout.CENTER);
|
mainPanel.add(activityPanel, BorderLayout.CENTER);
|
||||||
repack();
|
repack();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue