1 /* Copyright (C) 2005-2011 Fabio Riccardi */ 2 3 package com.lightcrafts.ui.operation; 4 5 import com.lightcrafts.model.Operation; 6 import static com.lightcrafts.ui.operation.Locale.LOCALE; 7 import com.lightcrafts.ui.toolkit.ImageOnlyButton; 8 import com.lightcrafts.utils.xml.XMLException; 9 import com.lightcrafts.utils.xml.XmlDocument; 10 11 import javax.swing.*; 12 import java.awt.event.ActionEvent; 13 import java.awt.event.ActionListener; 14 import java.awt.image.BufferedImage; 15 import java.io.ByteArrayInputStream; 16 import java.io.ByteArrayOutputStream; 17 import java.util.prefs.Preferences; 18 19 /** 20 * A title bar for OpControls, including a label for the Operation and 21 * standard controls like show/hide, enable/disable, and remove. 22 */ 23 24 class OpTitle extends SelectableTitle { 25 26 // Preferences are used to remember OpControl presets: 27 private final static Preferences Prefs = 28 Preferences.userNodeForPackage(OpTitle.class); 29 private final static String PresetsKey = "Presets"; 30 31 private OpControl control; 32 private JToggleButton activeButton; 33 private JButton removeButton; 34 private OpTitleEditor editor; 35 OpTitle(final OpControl control, final OpStack stack)36 OpTitle(final OpControl control, final OpStack stack) { 37 super(control); 38 this.control = control; 39 40 editor = new OpTitleEditor(this, control.undoSupport); 41 editor.setLabel(label); 42 43 Operation op = control.getOperation(); 44 BufferedImage image = OpActions.getIcon(op); 45 setIcon(image); 46 47 activeButton = createActiveButton(); 48 activeButton.setToolTipText(LOCALE.get("DisableToolTip")); 49 activeButton.setSelected(true); 50 activeButton.addActionListener( 51 new ActionListener() { 52 public void actionPerformed(ActionEvent event) { 53 boolean active = activeButton.isSelected(); 54 String tip; 55 if (active) { 56 tip = LOCALE.get("DisableToolTip"); 57 } 58 else { 59 tip = LOCALE.get("EnableToolTip"); 60 } 61 activeButton.setToolTipText(tip); 62 control.setActivated(activeButton.isSelected()); 63 } 64 } 65 ); 66 removeButton = createGoAwayButton(); 67 removeButton.setToolTipText(LOCALE.get("RemoveToolTip")); 68 removeButton.addActionListener( 69 new ActionListener() { 70 public void actionPerformed(ActionEvent event) { 71 stack.removeControl(control); 72 } 73 } 74 ); 75 if (! control.isSingleton()) { 76 buttonBox.add(activeButton); 77 // buttonBox.add(Box.createHorizontalStrut(ButtonSpace)); 78 buttonBox.add(removeButton); 79 // buttonBox.add(Box.createHorizontalStrut(ButtonSpace)); 80 } 81 } 82 getControl()83 OpControl getControl() { 84 return control; 85 } 86 setActive(boolean active)87 void setActive(boolean active) { 88 // Won't generate an ActionEvent, so no risk of recursion with the 89 // activeButton ActionListener: 90 activeButton.setSelected(active); 91 } 92 resetTitle(String title)93 void resetTitle(String title) { 94 super.resetTitle(title); 95 if (editor != null) { 96 // (Called from base class constructor, when editor may be null) 97 editor.setLabel(label); 98 } 99 } 100 createGoAwayButton()101 private static JButton createGoAwayButton() { 102 Icon normalIcon = getTitleIcon("x"); 103 Icon highlightIcon = getTitleIcon("x_H"); 104 Icon pressedIcon = getTitleIcon("x_S"); 105 JButton button = new ImageOnlyButton( 106 normalIcon, highlightIcon, pressedIcon, null 107 ); 108 // button.putClientProperty(SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY, Boolean.TRUE); 109 // button.putClientProperty(SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY, Boolean.TRUE); 110 // ImageOnlyButton.setStyle(button); 111 return button; 112 } 113 createActiveButton()114 private static JToggleButton createActiveButton() { 115 JToggleButton button = new JToggleButton(); 116 Icon normalIcon = getTitleIcon("nocheck"); 117 Icon selectedIcon = getTitleIcon("check"); 118 Icon normalHighlightIcon = getTitleIcon("nocheck_H"); 119 Icon selectedHighlightIcon = getTitleIcon("check_H"); 120 button.setIcon(normalIcon); 121 button.setSelectedIcon(selectedIcon); 122 button.setRolloverIcon(normalHighlightIcon); 123 button.setRolloverSelectedIcon(selectedHighlightIcon); 124 button.setRolloverEnabled(true); 125 // button.putClientProperty(SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY, Boolean.TRUE); 126 // button.putClientProperty(SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY, Boolean.TRUE); 127 ImageOnlyButton.setStyle(button); 128 return button; 129 } 130 getPopupMenu()131 JPopupMenu getPopupMenu() { 132 JPopupMenu menu = super.getPopupMenu(); 133 134 final OpStack stack = findOpStack(); 135 136 boolean isLocked = control.isLocked(); 137 138 if (! control.isSingleton()) { 139 if (! control.isActivated()) { 140 JMenuItem enableItem = new JMenuItem( 141 LOCALE.get("EnableMenuItem") 142 ); 143 enableItem.addActionListener( 144 new ActionListener() { 145 public void actionPerformed(ActionEvent event) { 146 control.setActivated(true); 147 } 148 } 149 ); 150 enableItem.setEnabled(! isLocked); 151 menu.add(enableItem, 0); 152 } 153 else { 154 JMenuItem disableItem = new JMenuItem( 155 LOCALE.get("DisableMenuItem") 156 ); 157 disableItem.addActionListener( 158 new ActionListener() { 159 public void actionPerformed(ActionEvent event) { 160 control.setActivated(false); 161 } 162 } 163 ); 164 disableItem.setEnabled(! isLocked); 165 menu.add(disableItem, 0); 166 } 167 menu.add(new JSeparator(), 1); 168 } 169 if (! isLocked) { 170 JMenuItem lockItem = new JMenuItem( 171 LOCALE.get("LockMenuItem") 172 ); 173 lockItem.addActionListener( 174 new ActionListener() { 175 public void actionPerformed(ActionEvent event) { 176 control.setLocked(true); 177 } 178 } 179 ); 180 menu.add(lockItem, 2); 181 } 182 else { 183 JMenuItem unlockItem = new JMenuItem( 184 LOCALE.get("UnlockMenuItem") 185 ); 186 unlockItem.addActionListener( 187 new ActionListener() { 188 public void actionPerformed(ActionEvent event) { 189 control.setLocked(false); 190 } 191 } 192 ); 193 menu.add(unlockItem, 2); 194 } 195 menu.add(new JSeparator(), 3); 196 197 JMenuItem savePreset = new JMenuItem( 198 LOCALE.get("RememberPresetMenuItem") 199 ); 200 savePreset.addActionListener( 201 new ActionListener() { 202 public void actionPerformed(ActionEvent event) { 203 XmlDocument preset = new XmlDocument("Preset"); 204 control.save(preset.getRoot()); 205 writePreset(preset); 206 } 207 } 208 ); 209 menu.add(savePreset, 4); 210 211 JMenuItem applyPreset = new JMenuItem( 212 LOCALE.get("ApplyPresetMenuItem") 213 ); 214 final XmlDocument preset = readPreset(); 215 applyPreset.addActionListener( 216 new ActionListener() { 217 public void actionPerformed(ActionEvent event) { 218 try { 219 // Like control.restore(), but with undo: 220 control.restorePresets(preset.getRoot()); 221 } 222 catch (XMLException e) { 223 // No way to back out of this, so leave things as 224 // they are and hope the user can recover. 225 System.err.println( 226 "Error in preset restore: " + e.getMessage() 227 ); 228 } 229 } 230 } 231 ); 232 if ((preset == null) || isLocked) { 233 applyPreset.setEnabled(false); 234 } 235 menu.add(applyPreset, 5); 236 237 if (! control.isSingleton()) { 238 JMenuItem deleteItem = new JMenuItem(LOCALE.get("DeleteMenuItem")); 239 deleteItem.addActionListener( 240 new ActionListener() { 241 public void actionPerformed(ActionEvent event) { 242 stack.removeControl(control); 243 } 244 } 245 ); 246 deleteItem.setEnabled(! isLocked); 247 248 menu.add(new JSeparator()); 249 250 menu.add(deleteItem); 251 } 252 return menu; 253 } 254 255 // Read in the preset for the current OpControl type from Preferences, 256 // or null if no such preset exists. readPreset()257 private XmlDocument readPreset() { 258 String key = getPresetsKey(); 259 String text = Prefs.get(key, ""); 260 try { 261 ByteArrayInputStream in = 262 new ByteArrayInputStream(text.getBytes("UTF-8")); 263 return new XmlDocument(in); 264 } 265 catch (Exception e) { // IOException or XMLException 266 return null; 267 } 268 } 269 270 // Save the given preset in Preferences for the current OpControl type. writePreset(XmlDocument preset)271 private void writePreset(XmlDocument preset) { 272 String key = getPresetsKey(); 273 try { 274 ByteArrayOutputStream out = new ByteArrayOutputStream(); 275 preset.write(out); 276 String text = out.toString("UTF-8"); 277 Prefs.put(key, text); 278 Prefs.sync(); 279 } 280 catch (Exception e) { // IOException or BackingStoreException 281 // Make sure the "Apply Preset" item doesn't get enabled: 282 Prefs.remove(key); 283 } 284 } 285 getPresetsKey()286 private String getPresetsKey() { 287 String name = control.getOperation().getType().getName(); 288 return PresetsKey + name; 289 } 290 } 291