org.pepsoft.worldpainter.layers.EditLayerDialog Maven / Gradle / Ivy
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.pepsoft.worldpainter.layers;
import org.pepsoft.worldpainter.App;
import org.pepsoft.worldpainter.ColourScheme;
import org.pepsoft.worldpainter.Dimension;
import org.pepsoft.worldpainter.Platform;
import org.pepsoft.worldpainter.biomeschemes.CustomBiomeManager;
import org.pepsoft.worldpainter.layers.exporters.ExporterSettings;
import org.pepsoft.worldpainter.layers.plants.PlantLayer;
import org.pepsoft.worldpainter.objects.MinecraftWorldObject;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Pepijn Schmitz
* @param The type of layer which the dialog should edit.
*/
public class EditLayerDialog extends AbstractEditLayerDialog implements LayerEditor.LayerEditorContext, ActionListener {
/**
* Creates new form EditLayerDialog for creating a new instance of a
* specific layer type.
*
* @param parent The window relative to which to display the dialog.
* @param layerType The type of layer of which to create a new instance.
*/
public EditLayerDialog(Window parent, Platform platform, Class layerType) {
this(parent, null, LayerEditorManager.getInstance().createEditor(platform, layerType));
}
/**
* Creates new form EditLayerDialog for editing an existing layer.
*
* @param parent The window relative to which to display the dialog.
* @param layer The layer to edit..
*/
@SuppressWarnings("unchecked") // Guaranteed by Java
public EditLayerDialog(Window parent, Platform platform, L layer) {
this(parent, layer, LayerEditorManager.getInstance().createEditor(platform, (Class) layer.getClass()));
}
private EditLayerDialog(Window parent, L layer, LayerEditor editor) {
super(parent);
if (editor == null) {
throw new IllegalArgumentException("No editor available for layer type" + ((layer != null) ? layer.getClass() : ""));
}
this.editor = editor;
if (layer == null) {
layer = editor.createLayer();
}
this.app = App.getInstance();
previewCreator = LayerPreviewCreator.createPreviewerForLayer(layer, app.getDimension());
initComponents();
if (! (layer instanceof CustomLayer)) {
setIconImage(layer.getIcon());
}
previewTimer.setRepeats(false);
editor.setContext(this);
editor.setLayer(layer);
JComponent editorComponent = editor.getComponent();
editorPanel.add(editorComponent, BorderLayout.CENTER);
// For some strange reason the look&feel isn't applied by Swing
SwingUtilities.updateComponentTreeUI(editorComponent);
int index = 0;
for (Component additionalButton: editor.getAdditionalButtons()) {
panelButtons.add(additionalButton, index++);
}
buttonOK.setEnabled(editor.isCommitAvailable());
jComboBox1.setModel(new DefaultComboBoxModel(LayerPreviewCreator.PATTERNS));
jComboBox1.setRenderer(new PatternListCellRenderer());
jComboBox1.setSelectedItem(previewCreator.getPattern());
dynMapPreviewer1.setZoom(-2);
dynMapPreviewer1.setInclination(30.0);
dynMapPreviewer1.setAzimuth(60.0);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
cancelPreviewUpdate();
}
});
scaleToUI();
pack();
if (! (layer instanceof PlantLayer)) {
scaleWindowToUI();
}
setLocationRelativeTo(parent);
getRootPane().setDefaultButton(buttonOK);
}
// AbstractEditLayerDialog
@Override
public L getLayer() {
return editor.getLayer();
}
// LayerEditorContext
@Override
public void settingsChanged() {
boolean commitAvailable = editor.isCommitAvailable();
buttonOK.setEnabled(commitAvailable);
if (commitAvailable) {
schedulePreviewUpdate();
} else {
cancelPreviewUpdate();
}
}
@Override
public Dimension getDimension() {
return app.getDimension();
}
@Override
public ColourScheme getColourScheme() {
return app.getColourScheme();
}
@Override
public boolean isExtendedBlockIds() {
return app.getWorld().isExtendedBlockIds();
}
@Override
public CustomBiomeManager getCustomBiomeManager() {
return app.getCustomBiomeManager();
}
@Override
public List getAllLayers() {
return new ArrayList<>(app.getAllLayers());
}
// ActionListener
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == previewTimer) {
updatePreview();
}
}
private void schedulePreviewUpdate() {
previewTimer.restart();
}
private void cancelPreviewUpdate() {
previewTimer.stop();
synchronized (PREVIEW_STATE_LOCK) {
// We can't interrupt an existing render, but we can make sure
// another one isn't started immediately after
if (previewRenderState == PreviewRenderState.SECOND_RENDER_SCHEDULED) {
previewRenderState = PreviewRenderState.RENDERING;
}
}
}
private void updatePreview() {
// TODO use Netherrack in addition to or instead of Grass, e.g. for Plants layer with Nether plants, etc.
// Check again whether the current settings are valid, although the
// chance is remote
if (! editor.isCommitAvailable()) {
return;
}
final ExporterSettings settings = editor.getSettings();
synchronized (PREVIEW_STATE_LOCK) {
switch (previewRenderState) {
case IDLE:
// Not rendering anything yet
new Thread("Preview Creator for " + editor.getLayer().getName()) {
@Override
public void run() {
renderLoop:
do {
synchronized (PREVIEW_RENDERER_LOCK) {
previewCreator.setLayer(settings.getLayer());
previewCreator.setSettings(settings);
final MinecraftWorldObject preview = previewCreator.renderPreview();
SwingUtilities.invokeLater(() -> dynMapPreviewer1.setObject(preview, app.getDimension()));
}
synchronized (PREVIEW_STATE_LOCK) {
switch (previewRenderState) {
case SECOND_RENDER_SCHEDULED:
previewRenderState = PreviewRenderState.RENDERING;
break; // Loop again
case RENDERING:
previewRenderState = PreviewRenderState.IDLE;
// Fall through to break loop
default:
// Break loop
break renderLoop;
}
}
} while(true);
}
}.start();
previewRenderState = PreviewRenderState.RENDERING;
break;
case RENDERING:
// A preview is already being rendered; set the state such
// that when it is finished another render will immediately
// be started
previewRenderState = PreviewRenderState.SECOND_RENDER_SCHEDULED;
break;
case SECOND_RENDER_SCHEDULED:
// A second render has already been scheduled for when the
// current render is finished. There is nothing more we can
// do
break;
}
}
}
private void updatePattern() {
previewCreator.setPattern((LayerPreviewCreator.Pattern) jComboBox1.getSelectedItem());
schedulePreviewUpdate();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
editorPanel = new javax.swing.JPanel();
dynMapPreviewer1 = new org.pepsoft.worldpainter.dynmap.DynmapPreviewer();
jComboBox1 = new javax.swing.JComboBox();
jLabel1 = new javax.swing.JLabel();
panelButtons = new javax.swing.JPanel();
buttonOK = new javax.swing.JButton();
buttonCancel = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Edit Layer Settings");
editorPanel.setLayout(new java.awt.BorderLayout());
dynMapPreviewer1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jComboBox1.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jComboBox1ActionPerformed(evt);
}
});
jLabel1.setText("Preview pattern:");
panelButtons.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 5, 0));
buttonOK.setText("OK");
buttonOK.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonOKActionPerformed(evt);
}
});
panelButtons.add(buttonOK);
buttonCancel.setText("Cancel");
buttonCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonCancelActionPerformed(evt);
}
});
panelButtons.add(buttonCancel);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(editorPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(dynMapPreviewer1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(panelButtons, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(editorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(dynMapPreviewer1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1))
.addGap(12, 12, 12)
.addComponent(panelButtons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
pack();
}// //GEN-END:initComponents
private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
cancel();
}//GEN-LAST:event_buttonCancelActionPerformed
private void buttonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOKActionPerformed
editor.commit();
ok();
}//GEN-LAST:event_buttonOKActionPerformed
private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox1ActionPerformed
updatePattern();
}//GEN-LAST:event_jComboBox1ActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton buttonCancel;
private javax.swing.JButton buttonOK;
private org.pepsoft.worldpainter.dynmap.DynmapPreviewer dynMapPreviewer1;
private javax.swing.JPanel editorPanel;
private javax.swing.JComboBox jComboBox1;
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel panelButtons;
// End of variables declaration//GEN-END:variables
private final LayerEditor editor;
private final Timer previewTimer = new Timer(1000, this);
private final LayerPreviewCreator previewCreator;
private final App app;
private PreviewRenderState previewRenderState = PreviewRenderState.IDLE;
/**
* This lock guards the preview rendering state.
*/
private static final Object PREVIEW_STATE_LOCK = new Object();
/**
* The preview renderer is stateful; this lock prevents more than one thread
* from using it at once.
*/
private static final Object PREVIEW_RENDERER_LOCK = new Object();
enum PreviewRenderState {IDLE, RENDERING, SECOND_RENDER_SCHEDULED}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy