*/
package jalview.gui;
-import jalview.api.FeatureRenderer;
-import jalview.bin.Cache;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SequenceI;
-import jalview.ext.rbvi.chimera.ChimeraCommands;
-import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
-import jalview.gui.StructureViewer.ViewerType;
-import jalview.io.DataSourceType;
-import jalview.io.StructureFile;
-import jalview.structures.models.AAStructureBindingModel;
-import jalview.util.BrowserLauncher;
-import jalview.util.MessageManager;
-import jalview.util.Platform;
-import jalview.ws.dbsources.Pdb;
-
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Random;
+import java.util.Map;
-import javax.swing.JCheckBoxMenuItem;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.bin.Console;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.StructureViewerModel;
+import jalview.datamodel.StructureViewerModel.StructureData;
+import jalview.ext.rbvi.chimera.JalviewChimeraBinding;
+import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
+import jalview.io.StructureFile;
+import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.ImageMaker.TYPE;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+
/**
* GUI elements for handling an external chimera display
*
{
private JalviewChimeraBinding jmb;
- private IProgressIndicator progressBar = null;
-
/*
* Path to Chimera session file. This is set when an open Jalview/Chimera
* session is saved, or on restore from a Jalview project (if it holds the
*/
private String chimeraSessionFile = null;
- private Random random = new Random();
-
private int myWidth = 500;
private int myHeight = 150;
+ private JMenuItem writeFeatures = null;
+
+ private JMenu fetchAttributes = null;
+
/**
* Initialise menu options.
*/
{
super.initMenus();
- viewerActionMenu.setText(MessageManager.getString("label.chimera"));
-
- viewerColour.setText(MessageManager
- .getString("label.colour_with_chimera"));
- viewerColour.setToolTipText(MessageManager
- .getString("label.let_chimera_manage_structure_colours"));
-
- helpItem.setText(MessageManager.getString("label.chimera_help"));
savemenu.setVisible(false); // not yet implemented
viewMenu.add(fitToWindow);
- JMenuItem writeFeatures = new JMenuItem(
- MessageManager.getString("label.create_chimera_attributes"));
- writeFeatures.setToolTipText(MessageManager
- .getString("label.create_chimera_attributes_tip"));
+ writeFeatures = new JMenuItem(
+ MessageManager.getString("label.create_viewer_attributes"));
+ writeFeatures.setToolTipText(
+ MessageManager.getString("label.create_viewer_attributes_tip"));
writeFeatures.addActionListener(new ActionListener()
{
@Override
});
viewerActionMenu.add(writeFeatures);
- final JMenu fetchAttributes = new JMenu(
- MessageManager.getString("label.fetch_chimera_attributes"));
- fetchAttributes.setToolTipText(MessageManager
- .getString("label.fetch_chimera_attributes_tip"));
+ fetchAttributes = new JMenu(MessageManager.formatMessage(
+ "label.fetch_viewer_attributes", getViewerName()));
+ fetchAttributes.setToolTipText(MessageManager.formatMessage(
+ "label.fetch_viewer_attributes_tip", getViewerName()));
fetchAttributes.addMouseListener(new MouseAdapter()
{
}
});
viewerActionMenu.add(fetchAttributes);
-
}
+ @Override
+ protected void buildActionMenu()
+ {
+ super.buildActionMenu();
+ // add these back in after menu is refreshed
+ viewerActionMenu.add(writeFeatures);
+ viewerActionMenu.add(fetchAttributes);
+
+ };
+
/**
- * Query Chimera for its residue attribute names and add them as items off the
- * attributes menu
+ * Query the structure viewer for its residue attribute names and add them as
+ * items off the attributes menu
*
* @param attributesMenu
*/
protected void buildAttributesMenu(JMenu attributesMenu)
{
- List<String> atts = jmb.sendChimeraCommand("list resattr", true);
- if (atts == null)
- {
- return;
- }
+ List<String> atts = jmb.getChimeraAttributes();
attributesMenu.removeAll();
Collections.sort(atts);
- for (String att : atts)
+ for (String attName : atts)
{
- final String attName = att.split(" ")[1];
-
- /*
- * ignore 'jv_*' attributes, as these are Jalview features that have
- * been transferred to residue attributes in Chimera!
- */
- if (!attName.startsWith(ChimeraCommands.NAMESPACE_PREFIX))
+ JMenuItem menuItem = new JMenuItem(attName);
+ menuItem.addActionListener(new ActionListener()
{
- JMenuItem menuItem = new JMenuItem(attName);
- menuItem.addActionListener(new ActionListener()
+ @Override
+ public void actionPerformed(ActionEvent e)
{
- @Override
- public void actionPerformed(ActionEvent e)
+ if (getBinding().copyStructureAttributesToFeatures(attName,
+ getAlignmentPanel()) > 0)
{
- getChimeraAttributes(attName);
+ getAlignmentPanel().getFeatureRenderer().featuresAdded();
}
- });
- attributesMenu.add(menuItem);
- }
+ }
+ });
+ attributesMenu.add(menuItem);
}
}
/**
- * Read residues in Chimera with the given attribute name, and set as features
- * on the corresponding sequence positions (if any)
- *
- * @param attName
- */
- protected void getChimeraAttributes(String attName)
- {
- jmb.copyStructureAttributesToFeatures(attName, getAlignmentPanel());
- }
-
- /**
- * Send a command to Chimera to create residue attributes for Jalview features
- * <p>
- * The syntax is: setattr r <attName> <attValue> <atomSpec>
- * <p>
- * For example: setattr r jv:chain "Ferredoxin-1, Chloroplastic" #0:94.A
+ * Sends command(s) to the structure viewer to create residue attributes for
+ * visible Jalview features
*/
protected void sendFeaturesToChimera()
{
+ // todo pull up?
int count = jmb.sendFeaturesToViewer(getAlignmentPanel());
statusBar.setText(MessageManager.formatMessage("label.attributes_set",
- count));
+ count, getViewerName()));
}
/**
- * add a single PDB structure to a new or existing Chimera view
+ * open a single PDB structure in a new Chimera view
*
* @param pdbentry
* @param seq
String[] chains, final AlignmentPanel ap)
{
this();
- String pdbId = pdbentry.getId();
- /*
- * If the PDB file is already loaded, the user may just choose to add to an
- * existing viewer (or cancel)
- */
- if (addAlreadyLoadedFile(seq, chains, ap, pdbId))
- {
- return;
- }
-
- /*
- * Check if there are other Chimera views involving this alignment and give
- * user the option to add and align this molecule to one of them (or cancel)
- */
- if (addToExistingViewer(pdbentry, seq, chains, ap, pdbId))
- {
- return;
- }
-
- /*
- * If the options above are declined or do not apply, show the structure in
- * a new viewer
- */
openNewChimera(ap, new PDBEntry[] { pdbentry },
- new SequenceI[][] { seq });
+ new SequenceI[][]
+ { seq });
}
/**
*/
protected void createProgressBar()
{
- if (progressBar == null)
+ if (getProgressIndicator() == null)
{
- progressBar = new ProgressBar(statusPanel, statusBar);
+ setProgressIndicator(new ProgressBar(statusPanel, statusBar));
}
}
SequenceI[][] seqs)
{
createProgressBar();
- jmb = new JalviewChimeraBindingModel(this,
- ap.getStructureSelectionManager(), pdbentrys, seqs, null);
+ jmb = newBindingModel(ap, pdbentrys, seqs);
addAlignmentPanel(ap);
useAlignmentPanelForColourbyseq(ap);
if (pdbentrys.length > 1)
{
- alignAddedStructures = true;
useAlignmentPanelForSuperposition(ap);
}
jmb.setColourBySequence(true);
this.addInternalFrameListener(new InternalFrameAdapter()
{
@Override
- public void internalFrameClosing(InternalFrameEvent internalFrameEvent)
+ public void internalFrameClosing(
+ InternalFrameEvent internalFrameEvent)
{
closeViewer(false);
}
}
+ protected JalviewChimeraBindingModel newBindingModel(AlignmentPanel ap,
+ PDBEntry[] pdbentrys, SequenceI[][] seqs)
+ {
+ return new JalviewChimeraBindingModel(this,
+ ap.getStructureSelectionManager(), pdbentrys, seqs, null);
+ }
+
/**
* Create a new viewer from saved session state data including Chimera session
* file
* @param colourBySequence
* @param newViewId
*/
- public ChimeraViewFrame(String chimeraSessionFile,
- AlignmentPanel alignPanel, PDBEntry[] pdbArray,
- SequenceI[][] seqsArray, boolean colourByChimera,
- boolean colourBySequence, String newViewId)
+ public ChimeraViewFrame(StructureViewerModel viewerData,
+ AlignmentPanel alignPanel, String sessionFile, String vid)
{
this();
- setViewId(newViewId);
- this.chimeraSessionFile = chimeraSessionFile;
+ setViewId(vid);
+ this.chimeraSessionFile = sessionFile;
+ Map<File, StructureData> pdbData = viewerData.getFileData();
+ PDBEntry[] pdbArray = new PDBEntry[pdbData.size()];
+ SequenceI[][] seqsArray = new SequenceI[pdbData.size()][];
+ int i = 0;
+ for (StructureData data : pdbData.values())
+ {
+ PDBEntry pdbentry = new PDBEntry(data.getPdbId(), null,
+ PDBEntry.Type.PDB, data.getFilePath());
+ pdbArray[i] = pdbentry;
+ List<SequenceI> sequencesForPdb = data.getSeqList();
+ seqsArray[i] = sequencesForPdb
+ .toArray(new SequenceI[sequencesForPdb.size()]);
+ i++;
+ }
openNewChimera(alignPanel, pdbArray, seqsArray);
- if (colourByChimera)
+ if (viewerData.isColourByViewer())
{
jmb.setColourBySequence(false);
seqColour.setSelected(false);
viewerColour.setSelected(true);
}
- else if (colourBySequence)
+ else if (viewerData.isColourWithAlignPanel())
{
jmb.setColourBySequence(true);
seqColour.setSelected(true);
}
/**
- * create a new viewer containing several structures superimposed using the
- * given alignPanel.
+ * create a new viewer containing several structures, optionally superimposed
+ * using the given alignPanel.
*
* @param pe
* @param seqs
* @param ap
*/
- public ChimeraViewFrame(PDBEntry[] pe, SequenceI[][] seqs,
- AlignmentPanel ap)
+ public ChimeraViewFrame(PDBEntry[] pe, boolean alignAdded,
+ SequenceI[][] seqs, AlignmentPanel ap)
{
this();
+ setAlignAddedStructures(alignAdded);
openNewChimera(ap, pe, seqs);
}
}
/**
- * Returns a list of any Chimera viewers in the desktop. The list is
- * restricted to those linked to the given alignment panel if it is not null.
- */
- @Override
- protected List<StructureViewerBase> getViewersFor(AlignmentPanel ap)
- {
- List<StructureViewerBase> result = new ArrayList<StructureViewerBase>();
- JInternalFrame[] frames = Desktop.instance.getAllFrames();
-
- for (JInternalFrame frame : frames)
- {
- if (frame instanceof ChimeraViewFrame)
- {
- if (ap == null || ((StructureViewerBase) frame).isLinkedWith(ap))
- {
- result.add((StructureViewerBase) frame);
- }
- }
- }
- return result;
- }
-
- /**
* Launch Chimera. If we have a chimera session file name, send Chimera the
* command to open its saved session file.
*/
if (!jmb.launchChimera())
{
JvOptionPane.showMessageDialog(Desktop.desktop,
- MessageManager.getString("label.chimera_failed"),
+ MessageManager.formatMessage("label.open_viewer_failed",
+ getViewerName()),
MessageManager.getString("label.error_loading_file"),
JvOptionPane.ERROR_MESSAGE);
+ jmb.closeViewer(true);
this.dispose();
return;
}
boolean opened = jmb.openSession(chimeraSessionFile);
if (!opened)
{
- System.err
- .println("An error occurred opening Chimera session file "
- + chimeraSessionFile);
+ jalview.bin.Console.errPrintln("An error occurred opening Chimera session file "
+ + chimeraSessionFile);
}
}
}
/**
- * Show only the selected chain(s) in the viewer
- */
- @Override
- void showSelectedChains()
- {
- List<String> toshow = new ArrayList<String>();
- for (int i = 0; i < chainMenu.getItemCount(); i++)
- {
- if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem)
- {
- JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i);
- if (item.isSelected())
- {
- toshow.add(item.getText());
- }
- }
- }
- jmb.showChains(toshow);
- }
-
- /**
- * Close down this instance of Jalview's Chimera viewer, giving the user the
- * option to close the associated Chimera window (process). They may wish to
- * keep it open until they have had an opportunity to save any work.
- *
- * @param closeChimera
- * if true, close any linked Chimera process; if false, prompt first
- */
- @Override
- public void closeViewer(boolean closeChimera)
- {
- if (jmb != null && jmb.isChimeraRunning())
- {
- if (!closeChimera)
- {
- String prompt = MessageManager.formatMessage(
- "label.confirm_close_chimera",
- new Object[] { jmb.getViewerTitle(getViewerName(),
- false) });
- prompt = JvSwingUtils.wrapTooltip(true, prompt);
- int confirm = JvOptionPane.showConfirmDialog(this, prompt,
- MessageManager.getString("label.close_viewer"),
- JvOptionPane.YES_NO_CANCEL_OPTION);
- /*
- * abort closure if user hits escape or Cancel
- */
- if (confirm == JvOptionPane.CANCEL_OPTION
- || confirm == JvOptionPane.CLOSED_OPTION)
- {
- return;
- }
- closeChimera = confirm == JvOptionPane.YES_OPTION;
- }
- jmb.closeViewer(closeChimera);
- }
- setAlignmentPanel(null);
- _aps.clear();
- _alignwith.clear();
- _colourwith.clear();
- // TODO: check for memory leaks where instance isn't finalised because jmb
- // holds a reference to the window
- jmb = null;
- dispose();
- }
-
- /**
* Open any newly added PDB structures in Chimera, having first fetched data
* from PDB (if not already saved).
*/
// todo - record which pdbids were successfully imported.
StringBuilder errormsgs = new StringBuilder(128);
StringBuilder files = new StringBuilder(128);
- List<PDBEntry> filePDB = new ArrayList<PDBEntry>();
- List<Integer> filePDBpos = new ArrayList<Integer>();
+ List<PDBEntry> filePDB = new ArrayList<>();
+ List<Integer> filePDBpos = new ArrayList<>();
PDBEntry thePdbEntry = null;
StructureFile pdb = null;
try
{
- String[] curfiles = jmb.getPdbFile(); // files currently in viewer
+ String[] curfiles = jmb.getStructureFiles(); // files currently in viewer
// TODO: replace with reference fetching/transfer code (validate PDBentry
// as a DBRef?)
for (int pi = 0; pi < jmb.getPdbCount(); pi++)
{
filePDB.add(thePdbEntry);
filePDBpos.add(Integer.valueOf(pi));
- files.append(" \"" + Platform.escapeString(file) + "\"");
+ files.append(" \"" + Platform.escapeBackslashes(file) + "\"");
}
}
} catch (OutOfMemoryError oomerror)
} catch (Exception ex)
{
ex.printStackTrace();
- errormsgs.append("When retrieving pdbfiles for '"
- + thePdbEntry.getId() + "'");
+ errormsgs.append(
+ "When retrieving pdbfiles for '" + thePdbEntry.getId() + "'");
}
if (errormsgs.length() > 0)
{
- JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager
- .formatMessage("label.pdb_entries_couldnt_be_retrieved",
- new Object[] { errormsgs.toString() }),
+ JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+ MessageManager.formatMessage(
+ "label.pdb_entries_couldnt_be_retrieved", new Object[]
+ { errormsgs.toString() }),
MessageManager.getString("label.couldnt_load_file"),
JvOptionPane.ERROR_MESSAGE);
}
initChimera();
} catch (Exception ex)
{
- Cache.log.error("Couldn't open Chimera viewer!", ex);
+ Console.error("Couldn't open Chimera viewer!", ex);
}
}
+ if (!jmb.isViewerRunning())
+ {
+ // nothing to do
+ // TODO: ensure we tidy up JAL-3619
+ return;
+ }
int num = -1;
for (PDBEntry pe : filePDB)
{
stopProgressBar("", startTime);
}
// Explicitly map to the filename used by Chimera ;
+
pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos],
- jmb.getChains()[pos], pe.getFile(), protocol);
- stashFoundChains(pdb, pe.getFile());
+ jmb.getChains()[pos], pe.getFile(), protocol,
+ getProgressIndicator());
+ jmb.stashFoundChains(pdb, pe.getFile());
+
} catch (OutOfMemoryError oomerror)
{
new OOMWarning(
oomerror);
} catch (Exception ex)
{
- Cache.log.error("Couldn't open " + pe.getFile()
- + " in Chimera viewer!", ex);
+ Console.error(
+ "Couldn't open " + pe.getFile() + " in Chimera viewer!",
+ ex);
} finally
{
- Cache.log.debug("File locations are " + files);
+ Console.debug("File locations are " + files);
}
}
}
/*
* ensure that any newly discovered features (e.g. RESNUM)
- * are added to any open feature settings dialog
+ * are notified to the FeatureRenderer (and added to any
+ * open feature settings dialog)
*/
FeatureRenderer fr = getBinding().getFeatureRenderer(null);
if (fr != null)
}
// refresh the sequence colours for the new structure(s)
- for (AlignmentPanel ap : _colourwith)
+ for (AlignmentViewPanel ap : _colourwith)
{
jmb.updateColours(ap);
}
// do superposition if asked to
- if (Cache.getDefault("AUTOSUPERIMPOSE", true) && alignAddedStructures)
+ if (alignAddedStructures)
{
new Thread(new Runnable()
{
@Override
public void run()
{
- alignStructs_withAllAlignPanels();
+ alignStructsWithAllAlignPanels();
}
}).start();
- alignAddedStructures = false;
}
addingStructures = false;
}
worker = null;
}
- /**
- * Fetch PDB data and save to a local file. Returns the full path to the file,
- * or null if fetch fails.
- *
- * @param processingEntry
- * @return
- * @throws Exception
- */
-
- private void stashFoundChains(StructureFile pdb, String file)
- {
- for (int i = 0; i < pdb.getChains().size(); i++)
- {
- String chid = new String(pdb.getId() + ":"
- + pdb.getChains().elementAt(i).id);
- jmb.getChainNames().add(chid);
- jmb.getChainFile().put(chid, file);
- }
- }
- private String fetchPdbFile(PDBEntry processingEntry) throws Exception
- {
- // FIXME: this is duplicated code with Jmol frame ?
- String filePath = null;
- Pdb pdbclient = new Pdb();
- AlignmentI pdbseq = null;
- String pdbid = processingEntry.getId();
- long handle = System.currentTimeMillis()
- + Thread.currentThread().hashCode();
-
- /*
- * Write 'fetching PDB' progress on AlignFrame as we are not yet visible
- */
- String msg = MessageManager.formatMessage("status.fetching_pdb",
- new Object[] { pdbid });
- getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
- // long hdl = startProgressBar(MessageManager.formatMessage(
- // "status.fetching_pdb", new Object[]
- // { pdbid }));
- try
- {
- pdbseq = pdbclient.getSequenceRecords(pdbid);
- } catch (OutOfMemoryError oomerror)
- {
- new OOMWarning("Retrieving PDB id " + pdbid, oomerror);
- } finally
- {
- msg = pdbid + " " + MessageManager.getString("label.state_completed");
- getAlignmentPanel().alignFrame.setProgressBar(msg, handle);
- // stopProgressBar(msg, hdl);
- }
- /*
- * If PDB data were saved and are not invalid (empty alignment), return the
- * file path.
- */
- if (pdbseq != null && pdbseq.getHeight() > 0)
- {
- // just use the file name from the first sequence's first PDBEntry
- filePath = new File(pdbseq.getSequenceAt(0).getAllPDBEntries()
- .elementAt(0).getFile()).getAbsolutePath();
- processingEntry.setFile(filePath);
- }
- return filePath;
- }
-
- /**
- * Convenience method to update the progress bar if there is one. Be sure to
- * call stopProgressBar with the returned handle to remove the message.
- *
- * @param msg
- * @param handle
- */
- public long startProgressBar(String msg)
- {
- // TODO would rather have startProgress/stopProgress as the
- // IProgressIndicator interface
- long tm = random.nextLong();
- if (progressBar != null)
- {
- progressBar.setProgressBar(msg, tm);
- }
- return tm;
- }
-
- /**
- * End the progress bar with the specified handle, leaving a message (if not
- * null) on the status bar
- *
- * @param msg
- * @param handle
- */
- public void stopProgressBar(String msg, long handle)
- {
- if (progressBar != null)
- {
- progressBar.setProgressBar(msg, handle);
- }
- }
-
@Override
- public void eps_actionPerformed(ActionEvent e)
+ public void makePDBImage(TYPE imageType)
{
- throw new Error(
- MessageManager
- .getString("error.eps_generation_not_implemented"));
- }
-
- @Override
- public void png_actionPerformed(ActionEvent e)
- {
- throw new Error(
- MessageManager
- .getString("error.png_generation_not_implemented"));
- }
-
- @Override
- public void showHelp_actionPerformed(ActionEvent actionEvent)
- {
- try
- {
- BrowserLauncher
- .openURL("https://www.cgl.ucsf.edu/chimera/docs/UsersGuide");
- } catch (IOException ex)
- {
- }
+ throw new UnsupportedOperationException(
+ "Image export for Chimera is not implemented");
}
@Override
return jmb;
}
- /**
- * Ask Chimera to save its session to the designated file path, or to a
- * temporary file if the path is null. Returns the file path if successful,
- * else null.
- *
- * @param filepath
- * @see getStateInfo
- */
- protected String saveSession(String filepath)
- {
- String pathUsed = filepath;
- try
- {
- if (pathUsed == null)
- {
- File tempFile = File.createTempFile("chimera", ".py");
- tempFile.deleteOnExit();
- pathUsed = tempFile.getPath();
- }
- boolean result = jmb.saveSession(pathUsed);
- if (result)
- {
- this.chimeraSessionFile = pathUsed;
- return pathUsed;
- }
- } catch (IOException e)
- {
- }
- return null;
- }
-
- /**
- * Returns a string representing the state of the Chimera session. This is
- * done by requesting Chimera to save its session to a temporary file, then
- * reading the file contents. Returns an empty string on any error.
- */
- @Override
- public String getStateInfo()
- {
- String sessionFile = saveSession(null);
- if (sessionFile == null)
- {
- return "";
- }
- InputStream is = null;
- try
- {
- File f = new File(sessionFile);
- byte[] bytes = new byte[(int) f.length()];
- is = new FileInputStream(sessionFile);
- is.read(bytes);
- return new String(bytes);
- } catch (IOException e)
- {
- return "";
- } finally
- {
- if (is != null)
- {
- try
- {
- is.close();
- } catch (IOException e)
- {
- // ignore
- }
- }
- }
- }
-
- @Override
- protected void fitToWindow_actionPerformed()
- {
- jmb.focusView();
- }
-
@Override
public ViewerType getViewerType()
{
{
return "Chimera";
}
-
- /**
- * Sends commands to align structures according to associated alignment(s).
- *
- * @return
- */
- @Override
- protected String alignStructs_withAllAlignPanels()
- {
- String reply = super.alignStructs_withAllAlignPanels();
- if (reply != null)
- {
- statusBar.setText("Superposition failed: " + reply);
- }
- return reply;
- }
}