1 package jp.ymir.taskReporter.ui
2 import java.awt.Dimension
3 import java.awt.event.ComponentAdapter
4 import java.awt.event.ComponentEvent
6 import javax.swing.JOptionPane
7 import javax.swing.JSplitPane
8 import javax.swing.KeyStroke
9 import javax.swing.event.MenuListener
10 import javax.swing.event.MenuEvent
11 import javax.swing.filechooser.FileNameExtensionFilter
12 import jp.ymir.taskReporter._
13 import jp.ymir.taskReporter.core._
15 import scala.swing.Swing._
16 import scala.swing.event._
18 class MainFrame(reportFile: Option[File]) extends Frame {
21 private val reportSet = new ReportSet(reportFile)
23 title = "Task Reporter " + Main.getVersion
24 preferredSize = Preferences.mainFrameSize()
26 case class FileOpened(file: File) extends Event
27 case class ReportSelected(report: Report) extends Event
28 case class ReportDeselected() extends Event
29 case class TaskSelected(task: Task) extends Event
30 case class TaskDeselected() extends Event
32 peer.addComponentListener(new ComponentAdapter() {
33 override def componentResized(e: ComponentEvent) {
34 Preferences.mainFrameSize() = size
38 menuBar = new MenuBar {
39 contents += new Menu("File") {
42 val miOpen = new MenuItem(new Action("Open...") {
43 accelerator = Some(KeyStroke getKeyStroke "control O")
45 val chooser = new FileChooser(Preferences.lastChosenDir()) {
46 fileSelectionMode = FileChooser.SelectionMode.FilesOnly
47 fileFilter = new FileNameExtensionFilter("TSV files", "tsv")
48 title = "Select a report file to open..."
49 peer.setAcceptAllFileFilterUsed(false)
51 val r = chooser.showOpenDialog(null)
52 if (r == FileChooser.Result.Approve) {
53 val file = chooser.selectedFile
54 Preferences.lastChosenDir() = file.getParentFile
56 frame publish FileOpened(file)
62 val miSave = new MenuItem(new Action("Save") {
63 accelerator = Some(KeyStroke.getKeyStroke("control S"));
68 contents += new Separator
70 contents += new MenuItem(new Action("Quit") {
71 accelerator = Some(KeyStroke.getKeyStroke("control Q"))
72 def apply = closeOperation
75 peer.addMenuListener(new MenuListener {
76 def menuSelected(e: MenuEvent) {
77 miOpen.enabled = !dirty
78 miSave.enabled = dirty
80 if (reportSet.file.isEmpty)
85 def menuDeselected(e: MenuEvent) {}
86 def menuCanceled(e: MenuEvent) {}
91 contents = new SplitPane {
92 peer.setOrientation(JSplitPane.HORIZONTAL_SPLIT)
93 continuousLayout = true
94 oneTouchExpandable = true
95 resizeWeight = 0 // Let the left pane be fixed
97 rightComponent = new BoxPanel(Orientation.Vertical) {
98 border = EmptyBorder(5, 5, 5, 5)
100 contents += new ScrollPane(
102 peer setFillsViewportHeight true
105 override def model : Report = super.model.asInstanceOf[Report]
108 case ReportSelected(report) =>
111 selection.rows += rowCount - 1 // Select the last report
113 case ReportDeselected() =>
114 model = new Report() // Empty report
117 selection.reactions += {
118 case TableRowsSelected(_, _, false) =>
119 selection.rows.size match {
121 val task = model(selection.rows.head)
122 frame publish TaskSelected(task)
124 frame publish TaskDeselected()
128 contents += VStrut(5)
129 contents += new TaskEditor {
132 case TaskSelected(t) => task = t
133 case TaskDeselected() => task = Task()
136 contents += VStrut(5)
137 contents += new FlowPanel(FlowPanel.Alignment.Left)() {
138 contents += new Button(new Action("New") {
139 def apply = {} // FIXME
141 contents += new Button(new Action("Delete...") {
142 def apply = {} // FIXME
147 leftComponent = new BorderPanel {
148 border = EmptyBorder(5, 5, 5, 5)
153 peer setFillsViewportHeight true
154 peer setModel reportSet
157 case FileOpened(f) =>
159 selection.rows += rowCount - 1 // Select the last report
162 selection.reactions += {
163 case TableRowsSelected(_, _, false) =>
164 selection.rows.size match {
166 val report = reportSet(selection.rows.head)
167 frame publish ReportSelected(report)
169 frame publish ReportDeselected()
172 }), BorderPanel.Position.Center)
175 new FlowPanel(FlowPanel.Alignment.Left)() {
176 contents += new Button(new Action("New...") {
177 def apply = {} // FIXME
179 contents += new Button(new Action("Delete...") {
180 def apply = {} // FIXME
182 }, BorderPanel.Position.South)
184 preferredSize = minimumSize
188 reportSet.file match {
189 case Some(file) => frame publish FileOpened(file)
190 case None => frame publish ReportDeselected()
196 override def closeOperation {
198 val r = JOptionPane.showConfirmDialog(
200 "The report file \"" + reportSet.file.get.getName + "\" has been modified.\n" +
201 "Do you want to save it before closing?",
203 JOptionPane.YES_NO_CANCEL_OPTION);
206 case JOptionPane.YES_OPTION => save; dispose
207 case JOptionPane.NO_OPTION => dispose
216 def dirty : Boolean = {
217 return reportSet.dirty
221 if (reportSet.file.isEmpty) {
222 val chooser = new FileChooser(Preferences.lastChosenDir())
223 val r = chooser.showSaveDialog(null)
224 if (r != FileChooser.Result.Approve) {
228 if (chooser.selectedFile.exists) {
229 val r = JOptionPane.showConfirmDialog(
231 "The chosen file or directory \"" + chooser.selectedFile.getName + "\" already exists.\n" +
232 "Do you want to overwrite it?",
234 JOptionPane.YES_NO_OPTION)
237 case JOptionPane.YES_OPTION =>
238 case JOptionPane.NO_OPTION => return
242 Preferences.lastChosenDir() = chooser.selectedFile.getParentFile
243 reportSet.save(chooser.selectedFile)