Mercurial > cgi-bin > hgweb.cgi > ImagePrep
comparison src/name/blackcap/imageprep/Menus.kt @ 0:e0efe7848130
Initial commit. Untested!
author | David Barts <davidb@stashtea.com> |
---|---|
date | Thu, 16 Jul 2020 19:57:23 -0700 |
parents | |
children | 0bded24f746e |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e0efe7848130 |
---|---|
1 /* | |
2 * Menus. | |
3 */ | |
4 package name.blackcap.imageprep | |
5 | |
6 import java.awt.Graphics2D | |
7 import java.awt.RenderingHints | |
8 import java.awt.Window | |
9 import java.awt.event.ActionEvent | |
10 import java.awt.event.ActionListener | |
11 import java.awt.event.KeyEvent | |
12 import java.awt.image.BufferedImage | |
13 import java.io.File | |
14 import java.util.logging.Level | |
15 import java.util.logging.Logger | |
16 import javax.imageio.IIOImage | |
17 import javax.imageio.ImageIO | |
18 import javax.imageio.ImageWriteParam | |
19 import javax.imageio.ImageWriter | |
20 import javax.imageio.stream.ImageOutputStream | |
21 import javax.swing.* | |
22 | |
23 /** | |
24 * Our menu bar. What we display depends somewhat on the system type, as | |
25 * the Mac gives us a gratuitous menu bar entry for handling some stuff. | |
26 */ | |
27 class MyMenuBar: JMenuBar() { | |
28 init { | |
29 add(JMenu("File").apply { | |
30 add(JMenuItem("Open & Scale…").apply { | |
31 addActionListener(ActionListener { doOpen() }) | |
32 makeShortcut(KeyEvent.VK_O) | |
33 }) | |
34 add(JMenuItem("Discard").apply { | |
35 addActionListener(ActionListener { doDiscard() }) | |
36 }) | |
37 add(JMenuItem("Save & Close…").apply { | |
38 addActionListener(ActionListener { doClose() }) | |
39 makeShortcut(KeyEvent.VK_S) | |
40 }) | |
41 if (OS.type != OS.MAC) { | |
42 add(JMenuItem("Preferences…").apply { | |
43 addActionListener(ActionListener { | |
44 Application.settingsDialog.setVisible(true) | |
45 }) | |
46 makeShortcut(KeyEvent.VK_COMMA) | |
47 }) | |
48 add(JMenuItem("Quit").apply { | |
49 addActionListener(ActionListener { | |
50 LOGGER.log(Level.INFO, "execution complete") | |
51 System.exit(0) | |
52 }) | |
53 makeShortcut(KeyEvent.VK_Q) | |
54 }) | |
55 } | |
56 }) | |
57 add(JMenu("Help").apply { | |
58 if (OS.type != OS.MAC) { | |
59 add(JMenuItem("About ${Application.MYNAME}…").apply { | |
60 addActionListener(ActionListener { showAboutDialog() }) | |
61 }) | |
62 } | |
63 add(JMenuItem("${Application.MYNAME} Help…").apply { | |
64 addActionListener(ActionListener { Application.helpDialog.setVisible(true) }) | |
65 }) | |
66 }) | |
67 } | |
68 | |
69 fun getMenu(name: String): JMenu? { | |
70 subElements.forEach { | |
71 val jmenu = it.component as? JMenu | |
72 if (jmenu?.text == name) { | |
73 return jmenu | |
74 } | |
75 } | |
76 return null | |
77 } | |
78 | |
79 private fun doOpen() { | |
80 val chooser = JFileChooser().apply { | |
81 fileFilter = FileNameExtensionFilter("Image files", ImageIO.getReaderFileSuffixes()) | |
82 } | |
83 if (chooser.showOpenDialog(Application.mainFrame) == JFileChooser.APPROVE_OPTION) { | |
84 RotateDialog.makeDialog(chooser.selectedFile) | |
85 } | |
86 } | |
87 | |
88 private fun doDiscard() { | |
89 val w = FocusManager.currentManager.activeWindow as? RotateDialog | |
90 if (w == null) { | |
91 Toolkit.defaultToolkit.beep() | |
92 return | |
93 } | |
94 w.setVisible(false) | |
95 w.dispose() | |
96 } | |
97 | |
98 private fun doClose() { | |
99 val w = FocusManager.currentManager.activeWindow as? RotateDialog | |
100 if (w == null) { | |
101 Toolkit.defaultToolkit.beep() | |
102 return | |
103 } | |
104 val outName = splitext(w.file.name).first + Settings.outputSuffix + ".jpg" | |
105 val chooser = JFileChooser(w).apply { | |
106 selectedFile = File( | |
107 if (Settings.outputToInputDir) w.file.parent else Settings.outputTo, | |
108 outName) | |
109 } | |
110 if (chooser.showOpenDialog(Application.mainFrame) != JFileChooser.APPROVE_OPTION) { | |
111 return | |
112 } | |
113 val (name, ext) = splitext(chooser.selectedFile.name) | |
114 val file = if (ext.toLowerCase() in setOf(".jpg", ".jpeg")) { | |
115 chooser.selectedFile | |
116 } else { | |
117 File(chooser.selectedFile.parent, name + ".jpg") | |
118 } | |
119 if (file.exists() && JOptionPane.showConfirmDialog(w, "File ${file.name} already exists. Overwrite?", "Confirm Overwrite", JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) { | |
120 return | |
121 } | |
122 w.useWaitCursor() | |
123 swingWorker<IOException?> { | |
124 inBackground { | |
125 try { | |
126 val ios = ImageIO.createImageOutputStream(file) | |
127 val writer = ImageIO.getImageWritersByFormatName("jpeg").next() | |
128 val iwp = writer.getDefaultWriteParam().apply { | |
129 setCompressionMode(ImageWriteParam.MODE_EXPLICIT) | |
130 setCompressionQuality(Settings.outputQuality.toFloat() / 100.0f) | |
131 } | |
132 writer.setOutput(ios) | |
133 writer.write(null, IIOImage(w.image, null, null), iwp) | |
134 null | |
135 } catch (e: IOException) { | |
136 e | |
137 } | |
138 } | |
139 whenDone { | |
140 w.useNormalCursor() | |
141 val error = get() | |
142 if (error == null) { | |
143 w.setVisible(false) | |
144 w.dispose() | |
145 } else { | |
146 ioExceptionDialog(w, file, "write", e) | |
147 } | |
148 } | |
149 } | |
150 } | |
151 | |
152 private fun splitext(s: String): Pair<String, String> { | |
153 val pos = s.lastIndexOf('.') | |
154 if (pos == -1) { | |
155 return Pair(s, "") | |
156 } | |
157 return Pair(s.substring(0, pos), s.substring(pos)) | |
158 } | |
159 } | |
160 | |
161 /** | |
162 * Show an About dialog. | |
163 */ | |
164 fun showAboutDialog() { | |
165 JOptionPane.showMessageDialog(Application.mainFrame, | |
166 "\nImagePrep\n" | |
167 + "\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0© MMXX, David W. Barts\n", | |
168 "About ImagePrep", | |
169 JOptionPane.PLAIN_MESSAGE) | |
170 } |