Wizard Sidebar Image

I think the code that causes the Wizard Sidebar Image to stretch when resized must lurk in the org.netbeans.modules.wizard package, but so far my google-fu has failed to find the source code for this online. Can anyone help me out?

Never mind. Figured it out :slight_smile:

Hi, Are you saying that you want the wizard sidebar image to stretch? I believe that the original Wizard source allowed that to happen, but Rodney specifically over-rode that behaviour because it looked so ghastly. That particular piece of the wizard source is in the Vassal source at org.netbeans.modules.wizard.InstructionsPanel.

The org.netbeans wizard library is truly ancient, but the source can be found if you look hard enough.

The stretching was being caused by duplicate InstructionsPanel .class files (one from your code directories and one from a precompiled jar). Mine kept grabbing the one from the jar, which scales, instead of the one in code, which does not. I renamed the InstructionsPanel class and changed WizardDisplayerImpl to use that version instead to fix the stretching.

I also added some code to add a seperate sidebar image to the wizard. I requested svn acces but didn’t get it, so I’ll just leave my code here to do with as you see fit :slight_smile:

Add the following line to Editor.properties:
Editor.GlobalOption.wizard_sidebar_image=Wizard Sidebar Image:

Code for GlobalOptions:
/*

  • $Id: GlobalOptions.java 9422 2020-05-25 21:47:04Z uckelman $
  • Copyright (c) 2000-2012 by Rodney Kinney, Brent Easton
  • This library is free software; you can redistribute it and/or
  • modify it under the terms of the GNU Library General Public
  • License (LGPL) as published by the Free Software Foundation.
  • This library is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  • Library General Public License for more details.
  • You should have received a copy of the GNU Library General Public
  • License along with this library; if not, copies are available
  • at opensource.org.
    */
    package VASSAL.build.module;

import java.awt.Container;
import java.awt.dnd.DragSource;
import java.awt.Image;
import java.io.File;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.swing.UIManager;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import org.apache.commons.lang3.SystemUtils;

import VASSAL.build.AbstractConfigurable;
import VASSAL.build.AutoConfigurable;
import VASSAL.build.Buildable;
import VASSAL.build.Builder;
import VASSAL.build.GameModule;
import VASSAL.build.IllegalBuildException;
import VASSAL.build.module.documentation.HelpFile;
import VASSAL.build.module.map.PieceMover;
import VASSAL.configure.BooleanConfigurer;
import VASSAL.configure.Configurer;
import VASSAL.configure.ConfigurerFactory;
import VASSAL.configure.FormattedStringConfigurer;
import VASSAL.configure.IntConfigurer;
import VASSAL.configure.SingleChildInstance;
import VASSAL.configure.StringEnum;
import VASSAL.i18n.Resources;
import VASSAL.preferences.BasicPreference;
import VASSAL.preferences.BooleanPreference;
import VASSAL.preferences.DoublePreference;
import VASSAL.preferences.EnumPreference;
import VASSAL.preferences.IntegerPreference;
import VASSAL.preferences.Prefs;
import VASSAL.preferences.StringPreference;
import VASSAL.preferences.TextPreference;
import VASSAL.tools.ErrorDialog;
import VASSAL.tools.FormattedString;
import VASSAL.tools.imageop.ImageOp;
import VASSAL.tools.imageop.Op;

public class GlobalOptions extends AbstractConfigurable {
public static final String NON_OWNER_UNMASKABLE = “nonOwnerUnmaskable”; //$NON-NLS-1$
public static final String PROMPT_STRING = “promptString”; //$NON-NLS-1$
public static final String CENTER_ON_MOVE = “centerOnMove”; //$NON-NLS-1$
public static final String MARK_MOVED = “markMoved”; //$NON-NLS-1$
public static final String AUTO_REPORT = “autoReport”; //$NON-NLS-1$
public static final String ALWAYS = “Always”; //$NON-NLS-1$
public static final String NEVER = “Never”; //$NON-NLS-1$
public static final String PROMPT = “Use Preferences Setting”; //$NON-NLS-1$
public static final String SINGLE_WINDOW = “singleWindow”; //$NON-NLS-1$
public static final String MAXIMUM_HEAP = “maximumHeap”; //$NON-NLS-1$
public static final String INITIAL_HEAP = “initialHeap”; //$NON-NLS-1$
public static final String BUG_10295 = “bug10295”;
public static final String WIZARD_SIDEBAR_IMAGE = “wizardSidebarImage”;

public static final String PLAYER_NAME = “PlayerName”; //$NON-NLS-1$
public static final String PLAYER_NAME_ALT = “playerName”; //$NON-NLS-1$
public static final String PLAYER_SIDE = “PlayerSide”; //$NON-NLS-1$
public static final String PLAYER_SIDE_ALT = “playerSide”; //$NON-NLS-1$
public static final String PLAYER_ID = “PlayerId”; //$NON-NLS-1$
public static final String PLAYER_ID_ALT = “playerId”; //$NON-NLS-1$
public static final String PLAYER_ID_FORMAT = “playerIdFormat”; //$NON-NLS-1$

private String promptString = “Opponents can unmask my pieces”; //$NON-NLS-1$
private String nonOwnerUnmaskable = NEVER;
private String centerOnMoves = ALWAYS;
private String autoReport = ALWAYS;
private String markMoved = NEVER;
private String wizardSidebarImage = “Wizard_Sidebar.png”;
private ImageOp op;
private Image image;

private Map<String,Object> properties = new HashMap<>();
private static Map<String,Configurer> optionConfigurers = new LinkedHashMap<>();
private static Properties optionInitialValues = new Properties();

private FormattedString playerIdFormat = new FormattedString("$" + PLAYER_NAME + “$”); //$NON-NLS-1$ //$NON-NLS-2$

private static GlobalOptions instance = new GlobalOptions();
private boolean useSingleWindow;

@Override
public void addTo(Buildable parent) {
instance = this;

final GameModule gm = GameModule.getGameModule();
final Prefs prefs = gm.getPrefs();

// should this moudule use a combined main window?
final BooleanConfigurer combConf = new BooleanConfigurer(
  SINGLE_WINDOW,
  Resources.getString("GlobalOptions.use_combined"),  //$NON-NLS-1$
  Boolean.TRUE
);
prefs.addOption(combConf);
useSingleWindow = !Boolean.FALSE.equals(combConf.getValue());

// the initial heap size for this module
final IntConfigurer initHeapConf = new IntConfigurer(
  INITIAL_HEAP,
  Resources.getString("GlobalOptions.initial_heap"),  //$NON-NLS-1$
  256
);
prefs.addOption(initHeapConf);

// the maximum heap size for this module
final IntConfigurer maxHeapConf = new IntConfigurer(
  MAXIMUM_HEAP,
  Resources.getString("GlobalOptions.maximum_heap"),  //$NON-NLS-1$
  512
);
prefs.addOption(maxHeapConf);

// Bug 10295: Sometimes, for unknown reasons, the native drag handler
// fails to draw images properly on Windows. This lets the user select
// the drag handler to use.
if (SystemUtils.IS_OS_WINDOWS) {
  final BooleanConfigurer bug10295Conf = new BooleanConfigurer(
    BUG_10295,
    Resources.getString("GlobalOptions.bug10295"),
    Boolean.FALSE
  );

  if (Boolean.TRUE.equals(bug10295Conf.getValue()) &&
        !(PieceMover.AbstractDragHandler.getTheDragHandler()
          instanceof PieceMover.DragHandlerNoImage))
  {
    PieceMover.AbstractDragHandler.setTheDragHandler(
      new PieceMover.DragHandlerNoImage()
    );
  }

  bug10295Conf.addPropertyChangeListener(new PropertyChangeListener() {
    @Override
    public void propertyChange(PropertyChangeEvent e) {
      PieceMover.AbstractDragHandler.setTheDragHandler(
        (Boolean.TRUE.equals(e.getNewValue()) ||
         !DragSource.isDragImageSupported()) ?
         new PieceMover.DragHandlerNoImage() :
         new PieceMover.DragHandler()
      );
    }
  });

  prefs.addOption(bug10295Conf);
}

validator = new SingleChildInstance(gm, getClass());

}

public static GlobalOptions getInstance() {
return instance;
}

public boolean isUseSingleWindow() {
return useSingleWindow;
}

@Deprecated
public boolean isAveragedScaling() {
return true;
}

public static String getConfigureTypeName() {
return Resources.getString(“Editor.GlobalOption.component_type”); //$NON-NLS-1$
}

public static class Prompt extends StringEnum {
@Override
public String[] getValidValues(AutoConfigurable target) {
return new String[]{ALWAYS, NEVER, PROMPT};
}
}

public static class PlayerIdFormatConfig implements ConfigurerFactory {
@Override
public Configurer getConfigurer(AutoConfigurable c, String key, String name) {
return new FormattedStringConfigurer(key, name, new String[]{PLAYER_NAME, PLAYER_SIDE});
}
}

@Override
public Class<?>[] getAllowableConfigureComponents() {
return new Class<?>[]{
StringPreference.class,
TextPreference.class,
EnumPreference.class,
IntegerPreference.class,
DoublePreference.class,
BooleanPreference.class
};
}

@Override
public String[] getAttributeDescriptions() {
return new String[]{
Resources.getString(“Editor.GlobalOption.nonowner_unmask”), //$NON-NLS-1$
null,
Resources.getString(“Editor.GlobalOption.center_moves”), //$NON-NLS-1$
Resources.getString(“Editor.GlobalOption.autoreport_moves”), //$NON-NLS-1$
Resources.getString(“Editor.GlobalOption.playerid_format”), //$NON-NLS-1$
Resources.getString(“Editor.GlobalOption.wizard_sidebar_image”) //$NON-NLS-1$
};
}

@Override
public String[] getAttributeNames() {
final ArrayList attributes = new ArrayList<>(
Arrays.asList(
NON_OWNER_UNMASKABLE,
PROMPT_STRING,
CENTER_ON_MOVE,
AUTO_REPORT,
PLAYER_ID_FORMAT,
WIZARD_SIDEBAR_IMAGE
)
);

for (String key : properties.keySet()) {
  attributes.add(key);
}

return attributes.toArray(new String[0]);

}

@Override
public Class<?>[] getAttributeTypes() {
return new Class<?>[]{
Prompt.class,
null,
Prompt.class,
Prompt.class,
PlayerIdFormatConfig.class,
Image.class
};
}

/**

  • Components may use GlobalOptions to store generic global attributes.
  • This method registers the given key as an attribute of the GlobalOptions
  • with the given type.
    */
    public void addOption(Configurer option) {
    optionConfigurers.put(option.getKey(), option);
    Object initValue = optionInitialValues.get(option.getKey());
if (initValue instanceof String) {
  option.setValue((String)initValue);
}

if (config != null) {
  ((Container)config.getControls()).add(option.getControls());
}

}

@Override
public void build(Element e) {
if (e == null) return;

final NamedNodeMap nnm = e.getAttributes();
for (int i = 0; i < nnm.getLength(); ++i) {
  final Attr att = (Attr) nnm.item(i);
  setAttribute(att.getName(), att.getValue());
}

for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
  if (n.getNodeType() == Node.ELEMENT_NODE) {
    final Element element = (Element) n;
    if ("option".equals(element.getTagName())) { //$NON-NLS-1$
      final String optionName = element.getAttribute("name"); //$NON-NLS-1$
      final String value = Builder.getText(element);
      optionInitialValues.put(optionName, value);
      // Update the Configurer value if it is already registered
      final Configurer config = optionConfigurers.get(optionName);
      if (config != null) {
        config.setValue(value);
      }
    }
    else {
      try {
        final Buildable b = Builder.create(element);
        b.addTo(this);
        add(b);
      }
      catch (IllegalBuildException ex) {
        ErrorDialog.bug(ex);
      }
    }
  }
}

}

@Override
public Element getBuildElement(Document doc) {
final Element e = super.getBuildElement(doc);
for (Configurer c : optionConfigurers.values()) {
final Element option = doc.createElement(“option”); //$NON-NLS-1$
option.setAttribute(“name”, c.getKey()); //$NON-NLS-1$
option.appendChild(doc.createTextNode(c.getValueString()));
e.appendChild(option);
}
return e;
}

@Override
public Configurer getConfigurer() {
if (config == null) {
final Configurer defaultConfig = super.getConfigurer();
for (Configurer c : optionConfigurers.values()) {
((Container) defaultConfig.getControls()).add(c.getControls());
}
}
return config;
}

@Override
public String getAttributeValueString(String key) {
if (NON_OWNER_UNMASKABLE.equals(key)) {
return nonOwnerUnmaskable;
}
else if (PROMPT_STRING.equals(key)) {
return promptString;
}
else if (CENTER_ON_MOVE.equals(key)) {
return centerOnMoves;
}
else if (AUTO_REPORT.equals(key)) {
return autoReport;
}
else if (MARK_MOVED.equals(key)) {
return markMoved;
}
else if (PLAYER_ID_FORMAT.equals(key)) {
return playerIdFormat.getFormat();
}
else if (WIZARD_SIDEBAR_IMAGE.equals(key)) {
return wizardSidebarImage;
}
else if (!optionConfigurers.containsKey(key)) {
Object val = properties.get(key);
return val != null ? val.toString() : null;
}
else {
return null;
}
}

@Override
public HelpFile getHelpFile() {
return HelpFile.getReferenceManualPage(“GlobalOptions.htm”); //$NON-NLS-1$
}

@Override
public void removeFrom(Buildable parent) {
}

@Override
public void setAttribute(String key, Object value) {
if (NON_OWNER_UNMASKABLE.equals(key)) {
nonOwnerUnmaskable = (String) value;
if (ALWAYS.equals(nonOwnerUnmaskable)) {
ObscurableOptions.getInstance().allowAll();
}
else if (NEVER.equals(nonOwnerUnmaskable)) {
ObscurableOptions.getInstance().allowNone();
}
else if (PROMPT.equals(nonOwnerUnmaskable)) {
ObscurableOptions.getInstance().allowSome(promptString);
GameModule.getGameModule().getGameState().addGameComponent(ObscurableOptions.getInstance());
GameModule.getGameModule().addCommandEncoder(ObscurableOptions.getInstance());
}
}
else if (PROMPT_STRING.equals(key)) {
promptString = (String) value;
ObscurableOptions.getInstance().setPrompt(promptString);
}
else if (CENTER_ON_MOVE.equals(key)) {
centerOnMoves = (String) value;
if (PROMPT.equals(centerOnMoves)) {
BooleanConfigurer config = new BooleanConfigurer(CENTER_ON_MOVE, Resources.getString(“GlobalOptions.center_on_move”)); //$NON-NLS-1$
GameModule.getGameModule().getPrefs().addOption(config);
}
}
else if (AUTO_REPORT.equals(key)) {
autoReport = (String) value;
if (PROMPT.equals(autoReport)) {
BooleanConfigurer config = new BooleanConfigurer(AUTO_REPORT, Resources.getString(“GlobalOptions.auto_report”)); //$NON-NLS-1$
GameModule.getGameModule().getPrefs().addOption(config);
}
}
else if (MARK_MOVED.equals(key)) {
markMoved = (String) value;
if (PROMPT.equals(markMoved)) {
BooleanConfigurer config = new BooleanConfigurer(MARK_MOVED, Resources.getString(“GlobalOptions.mark_moved”)); //$NON-NLS-1$
GameModule.getGameModule().getPrefs().addOption(config);
}
}
else if (PLAYER_ID_FORMAT.equals(key)) {
playerIdFormat.setFormat((String) value);
}
else if (WIZARD_SIDEBAR_IMAGE.equals(key)) {
if (value instanceof File) {
value = ((File) value).getName();
}
wizardSidebarImage = (String) value;

  op = null;
  if (wizardSidebarImage != null) {
    wizardSidebarImage = wizardSidebarImage.trim();
    if (wizardSidebarImage.length() > 0) {
      op = Op.load(wizardSidebarImage);

      final Image img = op.getImage();
      if (img != null) {
        UIManager.put("wizard.sidebar.image", img); //$NON-NLS-1$
      }
      else {
        op = null;
      }
    }
  }
}
else if (optionConfigurers.containsKey(key)) {
  optionConfigurers.get(key).setValue(value);
}
else {
  properties.put(key, value);
}

}

public boolean autoReportEnabled() {
return isEnabled(autoReport, AUTO_REPORT);
}

public boolean centerOnOpponentsMove() {
return isEnabled(centerOnMoves, CENTER_ON_MOVE);
}

public boolean isMarkMoveEnabled() {
return isEnabled(markMoved, MARK_MOVED);
}

public String getPlayerId() {
playerIdFormat.setProperty(PLAYER_NAME, (String) GameModule.getGameModule().getPrefs().getValue(GameModule.REAL_NAME));
playerIdFormat.setProperty(PLAYER_SIDE, PlayerRoster.getMyLocalizedSide());
return playerIdFormat.getText();
}

private boolean isEnabled(String attValue, String prefsPrompt) {
if (ALWAYS.equals(attValue)) {
return true;
}
else if (NEVER.equals(attValue)) {
return false;
}
else {
return Boolean.TRUE.equals(GameModule.getGameModule().getPrefs().getValue(prefsPrompt));
}
}

/**

  • Implement PropertyNameSource - Expose our preference names
    */
    @Override
    public List getPropertyNames() {
    final ArrayList l = new ArrayList<>();
    for (Buildable b : getBuildables()) {
    if (b instanceof BasicPreference) {
    l.add(((BasicPreference) b).getVariableName());
    }
    }
    return l;
    }

}

Hi Jeff,

Sorry you didn’t find us on SVN! We’re on github now – see github.com/vassalengine/vassal.

There are some useful getting-set-up materials on our wiki (see vassalengine.org/wiki/Building_Vassal)

Come join us! :slight_smile:

Brian