001/* 002 * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games. 003 * Copyright (C) 2000-2011 The Gridarta Developers. 004 * 005 * This program is free software; you can redistribute it and/or modify 006 * it under the terms of the GNU General Public License as published by 007 * the Free Software Foundation; either version 2 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License along 016 * with this program; if not, write to the Free Software Foundation, Inc., 017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 018 */ 019 020package net.sf.gridarta.gui.panel.tools; 021 022import java.awt.BorderLayout; 023import java.awt.CardLayout; 024import java.awt.Component; 025import java.awt.Container; 026import java.awt.FlowLayout; 027import java.awt.Insets; 028import java.awt.event.ActionEvent; 029import java.util.HashMap; 030import java.util.Map; 031import javax.swing.AbstractAction; 032import javax.swing.AbstractButton; 033import javax.swing.Action; 034import javax.swing.ButtonGroup; 035import javax.swing.JPanel; 036import javax.swing.JToggleButton; 037import net.sf.gridarta.gui.map.event.MouseOpListener; 038import net.sf.gridarta.gui.panel.objectchooser.ObjectChooser; 039import net.sf.gridarta.gui.panel.selectedsquare.SelectedSquareModel; 040import net.sf.gridarta.model.archetype.Archetype; 041import net.sf.gridarta.model.gameobject.GameObject; 042import net.sf.gridarta.model.maparchobject.MapArchObject; 043import net.sf.gridarta.model.mapmodel.InsertionModeSet; 044import net.sf.gridarta.model.mapviewsettings.MapViewSettings; 045import net.sf.gridarta.model.match.GameObjectMatcher; 046import net.sf.gridarta.model.pickmapsettings.PickmapSettings; 047import net.sf.japi.swing.action.ActionBuilder; 048import net.sf.japi.swing.action.ActionBuilderFactory; 049import org.jetbrains.annotations.NotNull; 050import org.jetbrains.annotations.Nullable; 051 052/** 053 * User interface for selecting a tool and displaying its options. Note: A 054 * ToolSelector automatically has always at least one Tool, the VoidTool. 055 * @author <a href="mailto:cher@riedquat.de">Christian Hujer</a> 056 */ 057public class ToolSelector<G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> extends JPanel { 058 059 /** 060 * The serial version UID. 061 */ 062 private static final long serialVersionUID = 1L; 063 064 /** 065 * The Action Builder. 066 */ 067 private static final ActionBuilder ACTION_BUILDER = ActionBuilderFactory.getInstance().getActionBuilder("net.sf.gridarta.gui.panel.tools"); 068 069 /** 070 * The pane with the selections. 071 */ 072 @NotNull 073 private final Container selectionPane = new JPanel(new FlowLayout()); 074 075 /** 076 * The CardLayout for the pane that shows a tool's options. 077 */ 078 @NotNull 079 private final CardLayout optionCards = new CardLayout(); 080 081 /** 082 * The ButtonGroup for the toggle buttons. 083 */ 084 @NotNull 085 private final ButtonGroup selectionButtonGroup = new ButtonGroup(); 086 087 /** 088 * The pane with the options of a tool. 089 */ 090 @NotNull 091 private final Container optionsPane = new JPanel(optionCards); 092 093 /** 094 * The currently selected tool. 095 */ 096 @NotNull 097 private Tool<G, A, R> selectedTool; 098 099 /** 100 * The tools. 101 */ 102 @NotNull 103 private final Map<String, Tool<G, A, R>> tools = new HashMap<String, Tool<G, A, R>>(); 104 105 /** 106 * Empty margin. 107 */ 108 private static final Insets EMPTY_MARGIN = new Insets(0, 0, 0, 0); 109 110 /** 111 * Creates a new instance. 112 * @param defaultTool name of the tool that should be selected by default 113 * @param mapViewSettings the map view settings instance 114 * @param selectedSquareModel the selected square model 115 * @param objectChooser the object chooser to use 116 * @param pickmapSettings the pickmap settings to use 117 * @param floorGameObjectMatcher the floor matcher to use 118 * @param wallGameObjectMatcher the wall matcher to use 119 * @param monsterGameObjectMatcher the monster matcher to use 120 * @param insertionModeSet the insertion mode set to use 121 */ 122 public ToolSelector(@NotNull final String defaultTool, @NotNull final MapViewSettings mapViewSettings, @NotNull final SelectedSquareModel<G, A, R> selectedSquareModel, @NotNull final ObjectChooser<G, A, R> objectChooser, @NotNull final PickmapSettings pickmapSettings, @Nullable final GameObjectMatcher floorGameObjectMatcher, @Nullable final GameObjectMatcher wallGameObjectMatcher, @Nullable final GameObjectMatcher monsterGameObjectMatcher, @NotNull final InsertionModeSet<G, A, R> insertionModeSet) { 123 createUI(); 124 addTool(new VoidTool<G, A, R>(), defaultTool); 125 addTool(new SelectionTool<G, A, R>(objectChooser, insertionModeSet), defaultTool); 126 addTool(new DeletionTool<G, A, R>(mapViewSettings, objectChooser, pickmapSettings, floorGameObjectMatcher, wallGameObjectMatcher, monsterGameObjectMatcher), defaultTool); 127 addTool(new InsertionTool<G, A, R>(selectedSquareModel, objectChooser, pickmapSettings, insertionModeSet, mapViewSettings), defaultTool); 128 } 129 130 /** 131 * Adds a tool to this tool selector. 132 * @param tool the tool to add 133 * @param defaultTool the name of the default tool 134 */ 135 private void addTool(@NotNull final Tool<G, A, R> tool, @NotNull final String defaultTool) { 136 add(tool, tool.getId().equals(defaultTool)); 137 } 138 139 /** 140 * Creates the user interface elements of the ToolSelector. 141 */ 142 private void createUI() { 143 setLayout(new BorderLayout()); 144 add(selectionPane, BorderLayout.NORTH); 145 add(optionsPane, BorderLayout.CENTER); 146 } 147 148 /** 149 * Adds a tool to this tool selector. 150 * @param tool the tool to add 151 */ 152 @SuppressWarnings("MethodOverloadsMethodOfSuperclass") 153 public void add(@NotNull final Tool<G, A, R> tool) { 154 add(tool, false); 155 } 156 157 /** 158 * Adds a tool to this tool selector. 159 * @param tool the tool to add 160 * @param selected <code>true</code> if the tool should be made the selected 161 * tool, otherwise <code>false</code> 162 */ 163 private void add(@NotNull final Tool<G, A, R> tool, final boolean selected) { 164 @NotNull final Action selectionAction = new SelectionAction(tool); 165 @NotNull final AbstractButton toggleButton = new JToggleButton(selectionAction); 166 toggleButton.setMargin(EMPTY_MARGIN); 167 @NotNull final Component optionsView = createOptionsView(tool); 168 selectionButtonGroup.add(toggleButton); 169 selectionPane.add(toggleButton); 170 final Container panel = new JPanel(new BorderLayout()); 171 panel.add(optionsView, BorderLayout.NORTH); 172 optionsPane.add(panel, tool.getId()); 173 toggleButton.setSelected(selected); 174 tools.put(tool.getId(), tool); 175 if (selected) { 176 selectedTool = tool; 177 optionCards.show(optionsPane, tool.getId()); 178 } 179 } 180 181 /** 182 * Creates the options view for a tool. This method is a delegate to {@link 183 * Tool#createOptionsView()} but will provide a fallback if the tool doesn't 184 * provide tweaking its options. 185 * @param tool the tool to create options view for 186 * @return the options view (the tool's options view or a dummy fallback if 187 * the tool doesn't provide an options view) 188 */ 189 @NotNull 190 private static <G extends GameObject<G, A, R>, A extends MapArchObject<A>, R extends Archetype<G, A, R>> Component createOptionsView(@NotNull final Tool<G, A, R> tool) { 191 @Nullable final Component optionsView = tool.createOptionsView(); 192 return optionsView != null ? optionsView : new JPanel(); 193 } 194 195 /** 196 * Makes a tool the currently selected tool to edit its options. 197 * @param tool the tool to select 198 * @pre the tool must be controlled by this tool-selector. 199 * @see #setSelectedTool(String) 200 */ 201 private void setSelectedTool(@NotNull final Tool<G, A, R> tool) { 202 selectedTool = tool; 203 optionCards.show(optionsPane, tool.getId()); 204 } 205 206 /** 207 * Makes a tool the currently selected tool to edit its options. This method 208 * exists to allow programs to store the currently selected tool in 209 * preferences and restore it after startup. 210 * @param id the ID of tool to select 211 * @pre the tool must be controlled by this tool-selector. 212 * @see #setSelectedTool(Tool) 213 * @see Tool#getId() 214 */ 215 public void setSelectedTool(@NotNull final String id) { 216 setSelectedTool(tools.get(id)); 217 } 218 219 /** 220 * Returns the tool that is currently selected. 221 * @return the currently selected tool 222 */ 223 @NotNull 224 public MouseOpListener<G, A, R> getSelectedTool() { 225 return selectedTool; 226 } 227 228 /** 229 * Action for selecting a tool. 230 */ 231 private class SelectionAction extends AbstractAction { 232 233 /** 234 * The serial version UID. 235 */ 236 private static final long serialVersionUID = 1L; 237 238 /** 239 * The tool to select with this action. 240 */ 241 @NotNull 242 private final Tool<G, A, R> tool; 243 244 /** 245 * Creates a SelectionAction. 246 * @param tool the tool to select with this action 247 */ 248 private SelectionAction(@NotNull final Tool<G, A, R> tool) { 249 this.tool = tool; 250 ACTION_BUILDER.initAction(false, this, tool.getId()); 251 } 252 253 @Override 254 public void actionPerformed(@NotNull final ActionEvent e) { 255 setSelectedTool(tool); 256 } 257 258 @Override 259 public Object clone() throws CloneNotSupportedException { 260 return super.clone(); 261 } 262 263 } 264 265}