1 /* Copyright (C) 2005-2011 Fabio Riccardi */ 2 3 package com.lightcrafts.app; 4 5 import static com.lightcrafts.app.Locale.LOCALE; 6 import com.lightcrafts.image.ImageInfo; 7 import com.lightcrafts.image.metadata.ImageMetadata; 8 import com.lightcrafts.image.types.RawImageType; 9 import com.lightcrafts.platform.Platform; 10 import com.lightcrafts.templates.TemplateKey; 11 import com.lightcrafts.templates.TemplateDatabase; 12 import com.lightcrafts.utils.xml.XMLException; 13 import com.lightcrafts.utils.xml.XmlDocument; 14 15 import javax.swing.*; 16 import java.awt.*; 17 import java.awt.event.*; 18 import java.io.File; 19 import java.io.FileInputStream; 20 import java.util.HashSet; 21 import java.util.List; 22 import java.util.Set; 23 24 /** 25 * The save-template dialog is a lot like a JOptionPane with a combo box, 26 * except it uses its own dialog instead of the JOptionPane showXxxDialog() 27 * methods so it can set the initial focus on the combo box instead of a 28 * button. 29 */ 30 class SaveTemplateDialog extends JDialog { 31 32 private XmlDocument originalTemplate; 33 private JComboBox namespaceField; 34 private JComboBox nameField; 35 private TemplateToolSelector selector; 36 private boolean isOkSelected; 37 private boolean isDefaultSelected; 38 showDialog( ImageMetadata meta, XmlDocument template, String nsDefault, JFrame parent )39 TemplateKey showDialog( 40 ImageMetadata meta, // offer the always-apply option for RAW images 41 XmlDocument template, // the template LZN to save 42 String nsDefault, // the default template namespace 43 JFrame parent // parent for this dialog 44 ) { 45 originalTemplate = template; 46 nameField = new JComboBox(); 47 namespaceField = new JComboBox(); 48 try { 49 // Find all distinct namespaces from the TemplateDocuments. 50 List<TemplateKey> keys = TemplateDatabase.getTemplateKeys(); 51 Set<String> namespaces = new HashSet<String>(); 52 for (TemplateKey key : keys) { 53 namespaces.add(key.getNamespace()); 54 } 55 for (String namespace : namespaces) { 56 namespaceField.addItem(namespace); 57 } 58 // Update the template names when the namespace changes. 59 namespaceField.addActionListener( 60 new ActionListener() { 61 public void actionPerformed(ActionEvent e) { 62 Object name = nameField.getSelectedItem(); 63 updateNameField(); 64 nameField.setSelectedItem(name); 65 } 66 } 67 ); 68 } 69 catch (TemplateDatabase.TemplateException e) { 70 // Just don't show existing template names. 71 } 72 try { 73 selector = new TemplateToolSelector(template); 74 } 75 catch (XMLException e) { 76 // Don't include the selector to the layout below. 77 System.err.println("Couldn't initialize TemplateToolSelector"); 78 e.printStackTrace(); 79 } 80 // Please excuse the GridBag. I'm just lining up text fields and 81 // labels into columns. 82 JPanel textGrid = new JPanel(new GridBagLayout()); 83 GridBagConstraints c = new GridBagConstraints(); 84 c.gridx = 0; 85 c.gridy = 0; 86 c.anchor = GridBagConstraints.EAST; 87 c.fill = GridBagConstraints.NONE; 88 textGrid.add(new JLabel(LOCALE.get("TemplateNameLabel") + ':'), c); 89 c.gridx = 1; 90 c.gridy = 0; 91 c.anchor = GridBagConstraints.WEST; 92 c.fill = GridBagConstraints.HORIZONTAL; 93 textGrid.add(nameField, c); 94 c.gridx = 0; 95 c.gridy = 1; 96 c.anchor = GridBagConstraints.EAST; 97 c.fill = GridBagConstraints.NONE; 98 textGrid.add(new JLabel(LOCALE.get("TemplateNamespaceLabel") + ':'), c); 99 c.gridx = 1; 100 c.gridy = 1; 101 c.anchor = GridBagConstraints.WEST; 102 c.fill = GridBagConstraints.HORIZONTAL; 103 textGrid.add(namespaceField, c); 104 105 // If a camera model is known, then offer the option to associate 106 // all images from this camera with the current template: 107 String camera = meta.getCameraMake(true); 108 boolean isRaw = (meta.getImageType() instanceof RawImageType); 109 JCheckBox defaultCheck; 110 if (isRaw && (camera != null)) { 111 defaultCheck = new JCheckBox( 112 LOCALE.get("TemplateAlwaysLabel", camera) 113 ); 114 } 115 else { 116 defaultCheck = new JCheckBox( 117 LOCALE.get("TemplateAlwaysDisabledLabel") 118 ); 119 defaultCheck.setEnabled(false); 120 } 121 defaultCheck.setAlignmentX(1f); 122 123 Box defaultBox = Box.createHorizontalBox(); 124 defaultBox.add(defaultCheck); 125 defaultBox.add(Box.createHorizontalGlue()); 126 127 // Initialize the text fields with a default template name: 128 if (nsDefault == null) { 129 nsDefault = LOCALE.get("TemplateDefaultNamespace"); 130 } 131 int n = 1; 132 String defaultName = null; 133 do { 134 String name = LOCALE.get( 135 "TemplateDefaultNamePattern", Integer.toString(n++) 136 ); 137 TemplateKey key = new TemplateKey(nsDefault, name); 138 try { 139 TemplateDatabase.getTemplateDocument(key); 140 } 141 catch (TemplateDatabase.TemplateException e) { 142 // No Template with this name has been defined. 143 defaultName = name; 144 } 145 } while (defaultName == null); 146 147 namespaceField.addItem(nsDefault); 148 namespaceField.setSelectedItem(nsDefault); 149 namespaceField.setEditable(true); 150 nameField.setPreferredSize( 151 new Dimension(160, namespaceField.getPreferredSize().height) 152 ); 153 nameField.getEditor().selectAll(); 154 155 nameField.addItem(defaultName); 156 nameField.setSelectedItem(defaultName); 157 nameField.setEditable(true); 158 nameField.setPreferredSize( 159 new Dimension(160, nameField.getPreferredSize().height) 160 ); 161 nameField.getEditor().selectAll(); 162 163 Box messageBox = Box.createVerticalBox(); 164 messageBox.add(textGrid); 165 messageBox.add(defaultBox); 166 messageBox.add(Box.createVerticalStrut(8)); 167 if (selector != null) { 168 messageBox.add(selector); 169 } 170 // We use our own OK button, instead of the one generated by 171 // JOptionPane, so we can set it to be the default button for the 172 // dialog. 173 JButton okButton = new JButton(LOCALE.get("TemplateSaveOption")); 174 JButton cancelButton = new JButton(LOCALE.get("TemplateCancelOption")); 175 JOptionPane pane = new JOptionPane( 176 messageBox, 177 JOptionPane.QUESTION_MESSAGE, 178 JOptionPane.OK_CANCEL_OPTION, 179 null, 180 new Object[] { okButton, cancelButton }, 181 null 182 ); 183 // Set a minimum width for the dialog. 184 Dimension size = pane.getPreferredSize(); 185 size = new Dimension(Math.max(size.width, 400), size.height); 186 pane.setPreferredSize(size); 187 188 // Use a custom dialog instead of the JOptionPane showXxxDialog() 189 // methods so that we can set the initial focus on the combo box 190 // instead of the OK button. 191 final JDialog dialog = new JDialog(parent); 192 dialog.setTitle(LOCALE.get("TemplateSaveDialogTitle")); 193 dialog.setContentPane(pane); 194 dialog.getRootPane().setDefaultButton(okButton); 195 196 // This causes the dialog to go away when the user presses "ESCAPE". 197 pane.registerKeyboardAction( 198 new ActionListener() { 199 public void actionPerformed(ActionEvent e) { 200 dialog.setVisible(false); 201 } 202 }, 203 KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), 204 JComponent.WHEN_IN_FOCUSED_WINDOW 205 ); 206 // This causes the dialog to go away when the user clicks "OK". 207 okButton.addActionListener( 208 new ActionListener() { 209 public void actionPerformed(ActionEvent e) { 210 211 // In case this happens while the combo box editor is 212 // active, commit the current text to the combo box model: 213 ComboBoxEditor editor = nameField.getEditor(); 214 JTextField text = (JTextField) editor.getEditorComponent(); 215 String name = text.getText(); 216 nameField.setSelectedItem(name); 217 218 isOkSelected = true; 219 dialog.setVisible(false); 220 } 221 } 222 ); 223 // This causes the dialog to go away when the user clicks "Cancel". 224 cancelButton.addActionListener( 225 new ActionListener() { 226 public void actionPerformed(ActionEvent event) { 227 dialog.setVisible(false); 228 } 229 } 230 ); 231 dialog.setModal(true); 232 dialog.setResizable(true); 233 dialog.pack(); 234 dialog.setLocationRelativeTo(parent); 235 236 dialog.setVisible(true); 237 238 isDefaultSelected = defaultCheck.isSelected(); 239 240 if (! isOkSelected) { 241 // The dialog was disposed, or the user clicked Cancel. 242 return null; 243 } 244 if (nameField.getEditor().getEditorComponent().isFocusOwner()) { 245 KeyboardFocusManager focus = 246 KeyboardFocusManager.getCurrentKeyboardFocusManager(); 247 focus.upFocusCycle(); 248 } 249 return new TemplateKey(getNamespaceText(), getNameText()); 250 } 251 getNameText()252 String getNameText() { 253 Object selected = nameField.getSelectedItem(); 254 return (selected != null) ? selected.toString() : ""; 255 } 256 getNamespaceText()257 String getNamespaceText() { 258 Object selected = namespaceField.getSelectedItem(); 259 return (selected != null) ? selected.toString() : ""; 260 } 261 isDefaultSelected()262 boolean isDefaultSelected() { 263 return isDefaultSelected; 264 } 265 getModifiedTemplate()266 XmlDocument getModifiedTemplate() { 267 if (selector != null) { 268 return selector.getModifiedTemplate(); 269 } 270 else { 271 return new XmlDocument(originalTemplate); 272 } 273 } 274 275 // When the namespace changes, update the combo box of Template names. updateNameField()276 private void updateNameField() { 277 String namespace = getNamespaceText(); 278 nameField.removeAllItems(); 279 try { 280 List<TemplateKey> descs = TemplateDatabase.getTemplateKeys(); 281 for (TemplateKey desc : descs) { 282 if (namespace.equals(desc.getNamespace())) { 283 nameField.addItem(desc.getName()); 284 } 285 } 286 } 287 catch (TemplateDatabase.TemplateException e) { 288 // Just leave the name field blank. 289 e.printStackTrace(); 290 } 291 } 292 main(String[] args)293 public static void main(String[] args) throws Exception { 294 UIManager.setLookAndFeel(Platform.getPlatform().getLookAndFeel()); 295 296 XmlDocument doc = new XmlDocument( 297 new FileInputStream( 298 "/Users/anton/test/1/test.lzn" 299 ) 300 ); 301 ImageInfo info = ImageInfo.getInstanceFor( 302 new File("/Users/anton/test/1/test.crw") 303 ); 304 ImageMetadata meta = info.getMetadata(); 305 306 SaveTemplateDialog dialog = new SaveTemplateDialog(); 307 dialog.showDialog(meta, doc, null, null); 308 309 System.out.println("name=" + dialog.getNameText()); 310 System.out.println("namespace=" + dialog.getNamespaceText()); 311 312 System.exit(0); 313 } 314 } 315